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
#include "debuggerdialogs.h"
#include "debuggerengine.h"
#include "debuggermainwindow.h"
con's avatar
con committed
38
#include "debuggerrunner.h"
39
#include "debuggerstringutils.h"
40
#include "debuggertooltip.h"
41
#include "debuggeruiswitcher.h"
42

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

56
#include "sessionengine.h"
57
58
#include "snapshothandler.h"
#include "threadshandler.h"
con's avatar
con committed
59

60
#include "ui_commonoptionspage.h"
hjk's avatar
hjk committed
61
#include "ui_dumperoptionpage.h"
62

63
#include <coreplugin/actionmanager/actionmanager.h>
64
65
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
66
#include <coreplugin/uniqueidmanager.h>
hjk's avatar
hjk committed
67
#include <coreplugin/basemode.h>
con's avatar
con committed
68
#include <coreplugin/coreconstants.h>
69
#include <coreplugin/dialogs/ioptionspage.h>
con's avatar
con committed
70
#include <coreplugin/editormanager/editormanager.h>
hjk's avatar
hjk committed
71
#include <coreplugin/findplaceholder.h>
72
#include <coreplugin/icontext.h>
con's avatar
con committed
73
#include <coreplugin/icore.h>
74
#include <coreplugin/imode.h>
75
#include <coreplugin/icorelistener.h>
76
#include <coreplugin/manhattanstyle.h>
hjk's avatar
hjk committed
77
#include <coreplugin/minisplitter.h>
con's avatar
con committed
78
#include <coreplugin/modemanager.h>
hjk's avatar
hjk committed
79

con's avatar
con committed
80
#include <cppeditor/cppeditorconstants.h>
81
#include <cpptools/cppmodelmanagerinterface.h>
hjk's avatar
hjk committed
82

83
84
#include <extensionsystem/pluginmanager.h>

85
#include <projectexplorer/project.h>
86
#include <projectexplorer/projectexplorer.h>
con's avatar
con committed
87
88
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>
89
#include <projectexplorer/target.h>
90
#include <projectexplorer/toolchaintype.h>
hjk's avatar
hjk committed
91
92

#include <texteditor/basetexteditor.h>
con's avatar
con committed
93
#include <texteditor/basetextmark.h>
94
#include <texteditor/fontsettings.h>
95
#include <texteditor/texteditorsettings.h>
hjk's avatar
hjk committed
96
97

#include <utils/qtcassert.h>
98
#include <utils/savedaction.h>
99
#include <utils/styledbar.h>
con's avatar
con committed
100

101
102
#include <qml/scriptconsole.h>

103
#include <QtCore/QTimer>
104
105
#include <QtCore/QtPlugin>
#include <QtGui/QComboBox>
106
#include <QtGui/QDockWidget>
107
108
#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
109
#include <QtGui/QToolButton>
con's avatar
con committed
110

111
112
#include <climits>

113
114
115
116
117
118
119
120
121
122
123
#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
124
// gdbserver, the trk client etc are referred to as 'Engine',
125
126
// whereas the debugged process is referred to as 'Inferior'.
//
127
128
// Transitions marked by '---' are done in the individual engines.
// Transitions marked by '+-+' are done in the base DebuggerEngine.
hjk's avatar
hjk committed
129
// Transitions marked by '*' are done asynchronously.
hjk's avatar
hjk committed
130
// The GdbEngine->setupEngine() function is described in more detail below.
131
//
hjk's avatar
hjk committed
132
133
134
135
136
137
138
// 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
139
140
141
142
143
144
//                        DebuggerNotReady
//                               +
//                      EngineSetupRequested
//                               +
//                  (calls *Engine->setupEngine())
//                            |      |
145
//                            |      |
hjk's avatar
hjk committed
146
147
148
//                       {notify-  {notify-
//                        Engine-   Engine-
//                        SetupOk}  SetupFailed}
149
150
151
152
153
154
//                            +      +
//                            +      `+-+-+> EngineSetupFailed
//                            +                   +
//                            +    [calls RunControl->startFailed]
//                            +                   +
//                            +             DebuggerFinished
hjk's avatar
hjk committed
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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 +-+-+-+-+-+->.
//                         +                                                +
//                         +                                                +
//                  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
189
//                                                                          +
Tobias Hunger's avatar
Tobias Hunger committed
190
//                       #Interrupt@InferiorRunOk#                           +
hjk's avatar
hjk committed
191
//                                  +                                       +
hjk's avatar
hjk committed
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//                          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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//                InferiorShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownInferior())                            +
//                         |        |                                       +
//                    {notify-   {notify-                                   +
//                     Inferior- Inferior-                                  +
//                  ShutdownOk}  ShutdownFailed}                            +
//                         +        +                                       +
//                         +        +                                       +
//  #Inferior exited#      +        +                                       +
//         |               +        +                                       +
//   {notifyInferior-      +        +                                       +
//      Exited}            +        +                                       +
//           +             +        +                                       +
//            +            +        +                                       +
//             +           +        +                                       +
//            InferiorShutdownOk InferiorShutdownFailed                     +
//                      *          *                                        +
//                  EngineShutdownRequested                                 +
//                            +                                             +
//           (calls *Engine->shutdownEngine())  <+-+-+-+-+-+-+-+-+-+-+-+-+-+' 
//                         |        |                                        
231
//                         |        |                                        
hjk's avatar
hjk committed
232
//                    {notify-   {notify-                                    
hjk's avatar
hjk committed
233
//                     Engine-    Engine-
hjk's avatar
hjk committed
234
235
236
237
238
//                  ShutdownOk}  ShutdownFailed}                             
//                         +       +                                         
//            EngineShutdownOk  EngineShutdownFailed                         
//                         *       *
//                     DebuggerFinished
239
240
241
/* 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
242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
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
276
// Additional signalling:    {notifyInferiorIll}   {notifyEngineIll}
hjk's avatar
hjk committed
277
278
279


// GdbEngine specific startup. All happens in EngineSetupRequested state
280
//
281
282
// Transitions marked by '---' are done in the individual adapters.
// Transitions marked by '+-+' are done in the GdbEngine.
hjk's avatar
hjk committed
283
//
hjk's avatar
hjk committed
284
//                  GdbEngine::setupEngine()
285
286
287
288
289
//                          +
//            (calls *Adapter->startAdapter())
//                          |      |
//                          |      `---> handleAdapterStartFailed()
//                          |                   +
hjk's avatar
hjk committed
290
//                          |             {notifyEngineSetupFailed}
291
292
293
//                          |
//                 handleAdapterStarted()
//                          +
hjk's avatar
hjk committed
294
295
296
297
298
299
//                 {notifyEngineSetupOk}
//
//
//
//                GdbEngine::setupInferior()
//                          +      
300
301
//            (calls *Adapter->prepareInferior())
//                          |      |
hjk's avatar
hjk committed
302
//                          |      `---> handlePrepareInferiorFailed()
303
//                          |                   +
hjk's avatar
hjk committed
304
//                          |             {notifyInferiorSetupFailed}
305
//                          |
hjk's avatar
hjk committed
306
//                handleInferiorPrepared()
307
//                          +
hjk's avatar
hjk committed
308
//                {notifyInferiorSetupOk}  
309
310
311
312




313

con's avatar
con committed
314
using namespace Core;
hjk's avatar
hjk committed
315
316
using namespace Debugger::Constants;
using namespace Debugger::Internal;
con's avatar
con committed
317
using namespace ProjectExplorer;
hjk's avatar
hjk committed
318
using namespace TextEditor;
con's avatar
con committed
319

hjk's avatar
hjk committed
320
321
322
namespace CC = Core::Constants;
namespace PE = ProjectExplorer::Constants;

con's avatar
con committed
323
324
325
326

namespace Debugger {
namespace Constants {

327
328
const char * const M_DEBUG_START_DEBUGGING = "QtCreator.Menu.Debug.StartDebugging";

con's avatar
con committed
329
330
const char * const STARTEXTERNAL        = "Debugger.StartExternal";
const char * const ATTACHEXTERNAL       = "Debugger.AttachExternal";
331
const char * const ATTACHCORE           = "Debugger.AttachCore";
hjk's avatar
hjk committed
332
const char * const ATTACHTCF            = "Debugger.AttachTcf";
333
const char * const ATTACHREMOTE         = "Debugger.AttachRemote";
334
const char * const DETACH               = "Debugger.Detach";
con's avatar
con committed
335

336
337
const char * const RUN_TO_LINE1         = "Debugger.RunToLine1";
const char * const RUN_TO_LINE2         = "Debugger.RunToLine2";
con's avatar
con committed
338
const char * const RUN_TO_FUNCTION      = "Debugger.RunToFunction";
339
340
const char * const JUMP_TO_LINE1        = "Debugger.JumpToLine1";
const char * const JUMP_TO_LINE2        = "Debugger.JumpToLine2";
341
const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
342
const char * const SNAPSHOT             = "Debugger.Snapshot";
con's avatar
con committed
343
344
345
const char * const TOGGLE_BREAK         = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION    = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN        = "Debugger.BreakAtMain";
346
347
const char * const ADD_TO_WATCH1        = "Debugger.AddToWatch1";
const char * const ADD_TO_WATCH2        = "Debugger.AddToWatch2";
348
const char * const OPERATE_BY_INSTRUCTION  = "Debugger.OperateByInstruction";
349
350
const char * const FRAME_UP             = "Debugger.FrameUp";
const char * const FRAME_DOWN           = "Debugger.FrameDown";
con's avatar
con committed
351

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
352
#ifdef Q_WS_MAC
con's avatar
con committed
353
const char * const STOP_KEY                 = "Shift+Ctrl+Y";
con's avatar
con committed
354
const char * const RESET_KEY                = "Ctrl+Shift+F5";
con's avatar
con committed
355
356
357
const char * const STEP_KEY                 = "Ctrl+Shift+I";
const char * const STEPOUT_KEY              = "Ctrl+Shift+T";
const char * const NEXT_KEY                 = "Ctrl+Shift+O";
358
const char * const REVERSE_KEY              = "";
con's avatar
con committed
359
360
const char * const RUN_TO_LINE_KEY          = "Shift+F8";
const char * const RUN_TO_FUNCTION_KEY      = "Ctrl+F6";
361
const char * const JUMP_TO_LINE_KEY         = "Ctrl+D,Ctrl+L";
con's avatar
con committed
362
const char * const TOGGLE_BREAK_KEY         = "F8";
363
364
365
366
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
367
#else
368
const char * const STOP_KEY                 = "Shift+F5";
con's avatar
con committed
369
370
371
372
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";
373
const char * const REVERSE_KEY              = "F12";
con's avatar
con committed
374
375
376
377
378
379
380
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";
381
const char * const SNAPSHOT_KEY             = "Ctrl+D,Ctrl+S";
con's avatar
con committed
382
383
384
385
386
387
#endif

} // namespace Constants
} // namespace Debugger


388

hjk's avatar
hjk committed
389
static SessionManager *sessionManager()
390
{
hjk's avatar
hjk committed
391
    return ProjectExplorerPlugin::instance()->session();
392
393
}

394
395
396
397
398
static QSettings *settings()
{
    return ICore::instance()->settings();
}

399
400
401
402
403
404
405
static QToolButton *toolButton(QAction *action)
{
    QToolButton *button = new QToolButton;
    button->setDefaultAction(action);
    return button;
}

406
407
408
namespace Debugger {
namespace Internal {

hjk's avatar
hjk committed
409
410
static const char *Role = "ROLE";

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
// 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) {}
428
    void clear();
429
430

    quint64 attachPid;
431
432
    QString attachTarget;  // core file name or  server:port
    // Event handle for attaching to crashed Windows processes. 
433
434
435
    quint64 winCrashEvent;
};

436
437
438
439
440
void AttachRemoteParameters::clear()
{
    attachPid = winCrashEvent = 0;
    attachTarget.clear();
}
441

442
443
444
445
446
447
///////////////////////////////////////////////////////////////////////
//
// DebugMode
//
///////////////////////////////////////////////////////////////////////

hjk's avatar
hjk committed
448
449
450
class DebugMode : public Core::BaseMode
{
public:
451
452
    DebugMode(QObject *parent = 0) : BaseMode(parent)
    {
453
        setDisplayName(QCoreApplication::translate("Debugger::Internal::DebugMode", "Debug"));
454
        setType(Core::Constants::MODE_EDIT_TYPE);
455
        setId(MODE_DEBUG);
456
        setIcon(QIcon(__(":/fancyactionbar/images/mode_Debug.png")));
457
458
        setPriority(P_MODE_DEBUG);
    }
hjk's avatar
hjk committed
459

460
461
462
463
464
465
    ~DebugMode()
    {
        // Make sure the editor manager does not get deleted.
        EditorManager::instance()->setParent(0);
    }
};
hjk's avatar
hjk committed
466

467

con's avatar
con committed
468
469
470
471
472
473
///////////////////////////////////////////////////////////////////////
//
// LocationMark
//
///////////////////////////////////////////////////////////////////////

474
// Used in "real" editors
475
class LocationMark : public TextEditor::BaseTextMark
con's avatar
con committed
476
477
478
479
{
public:
    LocationMark(const QString &fileName, int linenumber)
        : BaseTextMark(fileName, linenumber)
480
    {}
con's avatar
con committed
481

482
    QIcon icon() const { return DebuggerPlugin::instance()->locationMarkIcon(); }
con's avatar
con committed
483
484
    void updateLineNumber(int /*lineNumber*/) {}
    void updateBlock(const QTextBlock & /*block*/) {}
485
    void removedFromEditor() {}
con's avatar
con committed
486
487
};

488
489
490

///////////////////////////////////////////////////////////////////////
//
491
// CommonOptionsPage
492
493
494
//
///////////////////////////////////////////////////////////////////////

495
class CommonOptionsPage : public Core::IOptionsPage
496
497
{
public:
498
    CommonOptionsPage() {}
499
500

    // IOptionsPage
501
    QString id() const
hjk's avatar
hjk committed
502
        { return _(DEBUGGER_COMMON_SETTINGS_ID); }
503
    QString displayName() const
hjk's avatar
hjk committed
504
        { return QCoreApplication::translate("Debugger", DEBUGGER_COMMON_SETTINGS_NAME); }
505
    QString category() const
hjk's avatar
hjk committed
506
        { return _(DEBUGGER_SETTINGS_CATEGORY);  }
507
    QString displayCategory() const
hjk's avatar
hjk committed
508
        { return QCoreApplication::translate("Debugger", DEBUGGER_SETTINGS_TR_CATEGORY); }
509
510
    QIcon categoryIcon() const
        { return QIcon(QLatin1String(DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON)); }
511
512

    QWidget *createPage(QWidget *parent);
513
    void apply() { m_group.apply(settings()); }
514
    void finish() { m_group.finish(); }
515
    virtual bool matches(const QString &s) const;
516
517

private:
518
    Ui::CommonOptionsPage m_ui;
519
    Utils::SavedActionSet m_group;
520
    QString m_searchKeywords;
521
522
};

523
QWidget *CommonOptionsPage::createPage(QWidget *parent)
524
525
526
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);
527
    m_group.clear();
528

529
    m_group.insert(theDebuggerAction(ListSourceFiles),
530
        m_ui.checkBoxListSourceFiles);
531
    m_group.insert(theDebuggerAction(UseAlternatingRowColors),
532
        m_ui.checkBoxUseAlternatingRowColors);
533
    m_group.insert(theDebuggerAction(UseToolTipsInMainEditor),
534
        m_ui.checkBoxUseToolTipsInMainEditor);
535
536
537
538
    m_group.insert(theDebuggerAction(CloseBuffersOnExit),
        m_ui.checkBoxCloseBuffersOnExit);
    m_group.insert(theDebuggerAction(SwitchModeOnExit),
        m_ui.checkBoxSwitchModeOnExit);
539
    m_group.insert(theDebuggerAction(AutoDerefPointers), 0);
540
541
542
543
    m_group.insert(theDebuggerAction(UseToolTipsInLocalsView), 0);
    m_group.insert(theDebuggerAction(UseToolTipsInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInBreakpointsView), 0);
    m_group.insert(theDebuggerAction(UseAddressInStackView), 0);
544
    m_group.insert(theDebuggerAction(MaximalStackDepth),
545
        m_ui.spinBoxMaximalStackDepth);
546
547
    m_group.insert(theDebuggerAction(ShowStdNamespace), 0);
    m_group.insert(theDebuggerAction(ShowQtNamespace), 0);
548
    m_group.insert(theDebuggerAction(SortStructMembers), 0);
549
    m_group.insert(theDebuggerAction(LogTimeStamps), 0);
550
    m_group.insert(theDebuggerAction(VerboseLog), 0);
551
552
    m_group.insert(theDebuggerAction(BreakOnThrow), 0);
    m_group.insert(theDebuggerAction(BreakOnCatch), 0);
553
554
555
556
557
558
559
#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
560

561
    if (m_searchKeywords.isEmpty()) {
562
563
        QTextStream(&m_searchKeywords) << ' '
                << m_ui.checkBoxListSourceFiles->text()
564
565
                << ' ' << m_ui.checkBoxUseAlternatingRowColors->text()
                << ' ' << m_ui.checkBoxUseToolTipsInMainEditor->text()
566
567
568
#ifdef Q_OS_WIN
                << ' ' << m_ui.checkBoxRegisterForPostMortem->text()
#endif
569
570
571
                << ' ' << m_ui.labelMaximalStackDepth->text();
        m_searchKeywords.remove(QLatin1Char('&'));
    }
572
573
574
#ifndef Q_OS_WIN
    m_ui.checkBoxRegisterForPostMortem->setVisible(false);
#endif
575
576
577
    return w;
}

578
579
580
581
582
bool CommonOptionsPage::matches(const QString &s) const
{
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
}

hjk's avatar
hjk committed
583
584
///////////////////////////////////////////////////////////////////////
//
585
// DebuggingHelperOptionPage
hjk's avatar
hjk committed
586
587
588
//
///////////////////////////////////////////////////////////////////////

589
590
591
static inline bool oxygenStyle()
{
    if (const ManhattanStyle *ms = qobject_cast<const ManhattanStyle *>(qApp->style()))
592
        return !qstrcmp("OxygenStyle", ms->baseStyle()->metaObject()->className());
593
594
595
    return false;
}

596
class DebuggingHelperOptionPage : public Core::IOptionsPage
597
598
{   // Needs tr - context
    Q_OBJECT
hjk's avatar
hjk committed
599
public:
600
    DebuggingHelperOptionPage() {}
hjk's avatar
hjk committed
601
602

    // IOptionsPage
hjk's avatar
hjk committed
603
    QString id() const { return _("Z.DebuggingHelper"); }
604
    QString displayName() const { return tr("Debugging Helper"); }
hjk's avatar
hjk committed
605
    QString category() const { return _(DEBUGGER_SETTINGS_CATEGORY); }
606
607
608
609
    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
610
611

    QWidget *createPage(QWidget *parent);
612
    void apply() { m_group.apply(settings()); }
613
    void finish() { m_group.finish(); }
614
    virtual bool matches(const QString &s) const;
hjk's avatar
hjk committed
615
616

private:
617
    Ui::DebuggingHelperOptionPage m_ui;
618
    Utils::SavedActionSet m_group;
619
    QString m_searchKeywords;
hjk's avatar
hjk committed
620
621
};

622
QWidget *DebuggingHelperOptionPage::createPage(QWidget *parent)
hjk's avatar
hjk committed
623
624
625
626
{
    QWidget *w = new QWidget(parent);
    m_ui.setupUi(w);

627
    m_ui.dumperLocationChooser->setExpectedKind(Utils::PathChooser::Command);
628
    m_ui.dumperLocationChooser->setPromptDialogTitle(tr("Choose DebuggingHelper Location"));
hjk's avatar
hjk committed
629
630
    m_ui.dumperLocationChooser->setInitialBrowsePathBackup(
        Core::ICore::instance()->resourcePath() + "../../lib");
hjk's avatar
hjk committed
631

632
    m_group.clear();
633
    m_group.insert(theDebuggerAction(UseDebuggingHelpers),
634
        m_ui.debuggingHelperGroupBox);
635
    m_group.insert(theDebuggerAction(UseCustomDebuggingHelperLocation),
636
        m_ui.customLocationGroupBox);
hjk's avatar
hjk committed
637
    // Suppress Oxygen style's giving flat group boxes bold titles.
638
    if (oxygenStyle())
hjk's avatar
hjk committed
639
        m_ui.customLocationGroupBox->setStyleSheet(_("QGroupBox::title { font: ; }"));
640

641
    m_group.insert(theDebuggerAction(CustomDebuggingHelperLocation),
642
        m_ui.dumperLocationChooser);
hjk's avatar
hjk committed
643

644
645
646
    m_group.insert(theDebuggerAction(UseCodeModel),
        m_ui.checkBoxUseCodeModel);

647
#ifdef QT_DEBUG
648
649
    m_group.insert(theDebuggerAction(DebugDebuggingHelpers),
        m_ui.checkBoxDebugDebuggingHelpers);
650
651
652
#else
    m_ui.checkBoxDebugDebuggingHelpers->hide();
#endif
hjk's avatar
hjk committed
653
654
655
656

#ifndef QT_DEBUG
#if 0
    cmd = am->registerAction(m_manager->m_dumpLogAction,
hjk's avatar
hjk committed
657
        DUMP_LOG, globalcontext);
hjk's avatar
hjk committed
658
659
660
661
662
663
    //cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
    cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
    mdebug->addAction(cmd);
#endif
#endif

664
665
666
667
668
669
    if (m_searchKeywords.isEmpty()) {
        QTextStream(&m_searchKeywords)
                << ' ' << m_ui.debuggingHelperGroupBox->title()
                << ' ' << m_ui.customLocationGroupBox->title()
                << ' ' << m_ui.dumperLocationLabel->text()
                << ' ' << m_ui.checkBoxUseCodeModel->text()
670
                << ' ' << m_ui.checkBoxDebugDebuggingHelpers->text();
671
672
        m_searchKeywords.remove(QLatin1Char('&'));
    }
hjk's avatar
hjk committed
673
674
675
    return w;
}

676
bool DebuggingHelperOptionPage::matches(const QString &s) const
hjk's avatar
hjk committed
677
{
678
    return m_searchKeywords.contains(s, Qt::CaseInsensitive);
hjk's avatar
hjk committed
679
680
}

681

con's avatar
con committed
682
683
///////////////////////////////////////////////////////////////////////
//
684
// Argument parsing
con's avatar
con committed
685
686
687
//
///////////////////////////////////////////////////////////////////////

688
static QString msgParameterMissing(const QString &a)
689
690
691
692
{
    return DebuggerPlugin::tr("Option '%1' is missing the parameter.").arg(a);
}

693
static QString msgInvalidNumericParameter(const QString &a, const QString &number)
694
695
696
697
{
    return DebuggerPlugin::tr("The parameter '%1' of option '%2' is not a number.").arg(number, a);
}

698
static bool parseArgument(QStringList::const_iterator &it,
699
700
701
    const QStringList::const_iterator &cend,
    AttachRemoteParameters *attachRemoteParameters,
    unsigned *enabledEngines, QString *errorMessage)
702
703
704
{
    const QString &option = *it;
    // '-debug <pid>'
705
706
    // '-debug <corefile>'
    // '-debug <server:port>'
hjk's avatar
hjk committed
707
    if (*it == _("-debug")) {
708
709
710
711
712
713
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
714
        attachRemoteParameters->attachPid = it->toULongLong(&ok);
715
716
        if (!ok)
            attachRemoteParameters->attachTarget = *it;
717
718
        return true;
    }
719
720
    // -wincrashevent <event-handle>. A handle used for
    // a handshake when attaching to a crashed Windows process.
hjk's avatar
hjk committed
721
    if (*it == _("-wincrashevent")) {
722
723
724
725
726
727
        ++it;
        if (it == cend) {
            *errorMessage = msgParameterMissing(*it);
            return false;
        }
        bool ok;
728
        attachRemoteParameters->winCrashEvent = it->toULongLong(&ok);
729
730
731
732
733
734
        if (!ok) {
            *errorMessage = msgInvalidNumericParameter(option, *it);
            return false;
        }
        return true;
    }
hjk's avatar
hjk committed
735
    // Engine disabling.
hjk's avatar
hjk committed
736
    if (option == _("-disable-cdb")) {
737
        *enabledEngines &= ~Debugger::CdbEngineType;
738
739
        return true;
    }
hjk's avatar
hjk committed
740
    if (option == _("-disable-gdb")) {
741
        *enabledEngines &= ~Debugger::GdbEngineType;
742
743
        return true;
    }
744
745
746
747
    if (option == _("-disable-qmldb")) {
        *enabledEngines &= ~Debugger::QmlEngineType;
        return true;
    }
hjk's avatar
hjk committed
748
    if (option == _("-disable-sdb")) {
749
        *enabledEngines &= ~Debugger::ScriptEngineType;
750
751
        return true;
    }
752
    if (option == _("-disable-tcf")) {
hjk's avatar
hjk committed
753
754
755
        *enabledEngines &= ~TcfEngineType;
        return true;
    }
756

757
    *errorMessage = DebuggerPlugin::tr("Invalid debugger option: %1").arg(option);
758
759
760
    return false;
}

761
static bool parseArguments(const QStringList &args,
762
   AttachRemoteParameters *attachRemoteParameters,
hjk's avatar
hjk committed
763
   unsigned *enabledEngines, QString *errorMessage)
764
{
765
    attachRemoteParameters->clear();
766
767
    const QStringList::const_iterator cend = args.constEnd();
    for (QStringList::const_iterator it = args.constBegin(); it != cend; ++it)
768
        if (!parseArgument(it, cend, attachRemoteParameters, enabledEngines, errorMessage))
769
770
            return false;
    if (Debugger::Constants::Internal::debug)
771
        qDebug().nospace() << args << "engines=0x"
772
773
            << QString::number(*enabledEngines, 16)
            << " pid" << attachRemoteParameters->attachPid
774
            << " target" << attachRemoteParameters->attachTarget << '\n';
775
776
777
    return true;
}

778
779
780
781
782
783
784
785

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

static bool isDebuggable(Core::IEditor *editor)
786
{
787
788
789
790
791
792
793
794
    // 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;
795
796
}

797
static TextEditor::ITextEditor *currentTextEditor()
con's avatar
con committed
798
{
799
800
801
802
803
804
    EditorManager *editorManager = EditorManager::instance();
    if (!editorManager)
        return 0;
    Core::IEditor *editor = editorManager->currentEditor();
    return qobject_cast<ITextEditor*>(editor);
}
con's avatar
con committed
805

806
807
808
809
810
///////////////////////////////////////////////////////////////////////
//
// DebuggerPluginPrivate
//
///////////////////////////////////////////////////////////////////////
con's avatar
con committed
811

812
813
814
struct DebuggerActions
{
    QAction *continueAction;
815
816
817
    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
818
819
820
    QAction *resetAction; // FIXME: Should not be needed in a stable release
    QAction *stepAction;
    QAction *stepOutAction;
821
    QAction *runToLineAction; // Debug menu
822
    QAction *runToFunctionAction;
823
    QAction *jumpToLineAction; // in the Debug menu
824
825
826
827
828
829
830
831
832
833
834
    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
835

836
} // namespace Internal
con's avatar
con committed
837

838
using namespace Debugger::Internal;
con's avatar
con committed
839

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

846
847
848
class DebuggerPluginPrivate : public QObject
{
    Q_OBJECT
849

850
851
public:
    explicit DebuggerPluginPrivate(DebuggerPlugin *plugin);
852

853
854
    bool initialize(const QStringList &arguments, QString *errorMessage);
    void notifyCurrentEngine(int role, const QVariant &value = QVariant());
855
    void connectEngine(DebuggerEngine *engine, bool notify = true);
856
    void disconnectEngine() { connectEngine(m_sessionEngine); }
857

858
859
860
public slots:
    void updateWatchersHeader(int section, int, int newSize)
        { m_watchersWindow->header()->resizeSection(section, newSize); }
861

862
    void sourceFilesDockToggled(bool on)
hjk's avatar
hjk committed
863
        { if (on) notifyCurrentEngine(RequestReloadSourceFilesRole); }
864
    void modulesDockToggled(bool on)
hjk's avatar
hjk committed
865
866
867
        { if (on) notifyCurrentEngine(RequestReloadModulesRole); }
    void registerDockToggled(bool on)
        { if (on) notifyCurrentEngine(RequestReloadRegistersRole); }
868

869
870
871
872
873
874
875
876
877
878
    void synchronizeBreakpoints()
    {
        for (int i = 0, n = m_snapshotHandler->size(); i != n; ++i) {
            if (DebuggerRunControl *runControl = m_snapshotHandler->at(i)) {
                DebuggerEngine *engine = runControl->engine();
                engine->attemptBreakpointSynchronization();
            }
        }
    }

879
    void onAction();
880
    void setSimpleDockWidgetArrangement(Debugger::DebuggerLanguages activeLanguages);
881

882
883
884
885
886
887
888
    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);
889

890
891
892
893
894
895
    void activatePreviousMode();
    void activateDebugMode();
    void toggleBreakpoint();
    void toggleBreakpoint(const QString &fileName, int lineNumber);
    void onModeChanged(Core::IMode *mode);
    void showSettingsDialog();
896

897
898
899
900
901
    void startExternalApplication();
    void startRemoteApplication();
    void attachExternalApplication();
    void attachExternalApplication
        (qint64 pid, const QString &binary, const QString &crashParameter);
902
    bool attachCmdLine();
903
904
    void attachCore();
    void attachCore(const QString &core, const QString &exeFileName);
905
    void attachRemote(const QString &spec);
906
    void attachRemoteTcf();
907

908
    void enableReverseDebuggingTriggered(const QVariant &value);
909
    void languagesChanged(const Debugger::DebuggerLanguages &languages);
910
    void showStatusMessage(const QString &msg, int timeout = -1);
911
    void openMemoryEditor();
912
913
914
915
916

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

917
918
    inline void setConfigValue(const QString &name, const QVariant &value);
    inline QVariant configValue(const QString &name) const;
919

ck's avatar
ck committed
920
    DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp,
hjk's avatar
hjk committed
921
922
        RunConfiguration *rc = 0);
    void startDebugger(RunControl *runControl);
923
    void displayDebugger(DebuggerEngine *engine, bool updateEngine = true);
924
925
926

    void dumpLog();
    void cleanupViews();
927
    void setInitialState();
928
929
930
931
932

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

    void updateState(DebuggerEngine *engine);
933
    void onCurrentProjectChanged(ProjectExplorer::Project *project);
934
935
936
937
938
939
940
941

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

    void clearStatusMessage();

    void sessionLoaded();
    void aboutToUnloadSession();
    void aboutToSaveSession();
942
943

    void executeDebuggerCommand();
hjk's avatar
hjk committed
944
    void scriptExpressionEntered(const QString &expression);
945
    void coreShutdown();
946

947
948
949
950
951
952
953
954
public:
    DebuggerState m_state;
    DebuggerUISwitcher *m_uiSwitcher;
    DebuggerPlugin *m_manager;
    DebugMode *m_debugMode;
    DebuggerRunControlFactory *m_debuggerRunControlFactory;

    QString m_previousMode;
955
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
956
957
    Core::Context m_continuableContext;
    Core::Context m_interruptibleContext;
958
959
960
    Core::Context m_undisturbableContext;
    Core::Context m_finishedContext;
    Core::Context m_anyContext;
961
962
963
964
965
966
967
968
969
970
971
    AttachRemoteParameters m_attachRemoteParameters;

    QAction *m_startExternalAction;
    QAction *m_startRemoteAction;
    QAction *m_attachExternalAction;
    QAction *m_attachCoreAction;
    QAction *m_attachTcfAction;
    QAction *m_detachAction;
    QComboBox *m_langBox;
    QToolButton *m_reverseToolButton;

972
    QIcon m_startIcon;
973
    QIcon m_stopIcon;
974
    QIcon m_continueIcon;
975
976
977
978
979
980
981
    QIcon m_interruptIcon;
    QIcon m_locationMarkIcon;

    QLabel *m_statusLabel;
    QComboBox *m_threadBox;

    QDockWidget *m_breakDock;
982
    //QDockWidget *m_consoleDock;
983
984
985
986
987
988
989
990
    QDockWidget *m_modulesDock;
    QDockWidget *m_outputDock;
    QDockWidget *m_registerDock;
    QDockWidget *m_snapshotDock;
    QDockWidget *m_sourceFilesDock;
    QDockWidget *m_stackDock;
    QDockWidget *m_threadsDock;
    QDockWidget *m_watchDock;
991
992
    QDockWidget* m_scriptConsoleDock;

993
994
995
    DebuggerActions m_actions;

    BreakWindow *m_breakWindow;
996
    BreakHandler *m_breakHandler;
997
    //ConsoleWindow *m_consoleWindow;
998
999
1000
1001
1002
1003
1004
1005
1006
1007
    QTreeView *m_returnWindow;
    QTreeView *m_localsWindow;
    QTreeView *m_watchersWindow;
    QTreeView *m_commandWindow;
    QAbstractItemView *m_registerWindow;
    QAbstractItemView *m_modulesWindow;
    QAbstractItemView *m_snapshotWindow;
    SourceFilesWindow *m_sourceFilesWindow;
    QAbstractItemView *m_stackWindow;
    QAbstractItemView *m_threadsWindow;
1008
    LogWindow *m_logWindow;
1009
    ScriptConsole *m_scriptConsoleWindow;