debuggermanager.cpp 65.5 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
**************************************************************************/
con's avatar
con committed
29
30
31

#include "debuggermanager.h"

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

#include "breakwindow.h"
#include "debuggeroutputwindow.h"
#include "moduleswindow.h"
#include "registerwindow.h"
47
#include "snapshotwindow.h"
con's avatar
con committed
48
#include "stackwindow.h"
49
#include "sourcefileswindow.h"
con's avatar
con committed
50
51
52
53
54
55
#include "threadswindow.h"
#include "watchwindow.h"

#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
56
#include "snapshothandler.h"
con's avatar
con committed
57
#include "stackhandler.h"
58
#include "stackframe.h"
con's avatar
con committed
59
60
#include "watchhandler.h"

61
#include "debuggerdialogs.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
62
#ifdef Q_OS_WIN
63
#  include "shared/peutils.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
64
#endif
65

66
#include <coreplugin/icore.h>
67
#include <coreplugin/minisplitter.h>
68
#include <coreplugin/editormanager/editormanager.h>
69
#include <utils/qtcassert.h>
70
#include <utils/savedaction.h>
71
#include <projectexplorer/toolchain.h>
72
73
#include <cplusplus/CppDocument.h>
#include <cpptools/cppmodelmanagerinterface.h>
74
#include <qt4projectmanager/qt4projectmanagerconstants.h>
75
#include <texteditor/fontsettings.h>
76
#include <texteditor/itexteditor.h>
77

con's avatar
con committed
78
79
80
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
81
#include <QtCore/QTextStream>
con's avatar
con committed
82
#include <QtCore/QTime>
83
#include <QtCore/QTimer>
con's avatar
con committed
84

85
#include <QtGui/QApplication>
con's avatar
con committed
86
87
88
89
90
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
91
#include <QtGui/QHeaderView>
con's avatar
con committed
92
93
94
#include <QtGui/QLabel>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
95
#include <QtGui/QPushButton>
con's avatar
con committed
96
97
98
99
100
101
#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>

102
103
104
105
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
// use  Q_FUNC_INFO?
#   define STATE_DEBUG(s) \
hjk's avatar
hjk committed
106
107
    do { QString msg; QTextStream ts(&msg); ts << s; \
      showDebuggerOutput(LogDebug, msg); } while (0)
108
109
110
111
#else
#   define STATE_DEBUG(s)
#endif

112
113
// Note: the Debugger process itself and any helper processes like
// gdbserver, the trk client etc are referred to as 'Adapter',
hjk's avatar
hjk committed
114
115
// whereas the debugged process is referred to as 'Inferior'.
//
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
116
//              0 == DebuggerNotReady
hjk's avatar
hjk committed
117
//                          |
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
118
//                    EngineStarting
hjk's avatar
hjk committed
119
//                          |
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
120
//                    AdapterStarting --> AdapterStartFailed --> 0
hjk's avatar
hjk committed
121
//                          |
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//                    AdapterStarted ------------------------------------.
//                          |                                            v
//                   InferiorStarting ----> InferiorStartFailed -------->|
//                          |                                            |
//         (core)           |     (attach) (term) (remote)               |
//      .-----------------<-|->------------------.                       |
//      |                   v                    |                       |
//  InferiorUnrunnable      | (plain)            |                       |
//      |                   | (trk)              |                       |
//      |                   |                    |                       |
//      |    .--> InferiorRunningRequested       |                       |
//      |    |              |                    |                       |
//      |    |       InferiorRunning             |                       |
//      |    |              |                    |                       |
//      |    |       InferiorStopping            |                       |
//      |    |              |                    |                       |
//      |    '------ InferiorStopped <-----------'                       |
//      |                   |                                            v
//      |          InferiorShuttingDown  ->  InferiorShutdownFailed ---->|
//      |                   |                                            |
//      |            InferiorShutDown                                    |
//      |                   |                                            |
//      '-------->  EngineShuttingDown  <--------------------------------'
hjk's avatar
hjk committed
145
146
//                          |
//                          0
hjk's avatar
hjk committed
147
148
149
150
151
152
//
// Allowed actions:
//    [R] :  Run
//    [C] :  Continue
//    [N] :  Step, Next

153
154
namespace Debugger {
namespace Internal {
155

156
157
IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
hjk's avatar
hjk committed
158
IDebuggerEngine *createPdbEngine(DebuggerManager *parent);
159

hjk's avatar
hjk committed
160
// The createCdbEngine function takes a list of options pages it can add to.
161
162
163
// 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.
164

hjk's avatar
hjk committed
165
IDebuggerEngine *createCdbEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
166
167
168
169
170
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
171

172
} // namespace Internal
173

174
DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
175
176
177
178
179
180
181
182
183
184
{
    QDebug nospace = str.nospace();
    const QString sep = QString(QLatin1Char(','));
    nospace << "executable=" << p.executable << " coreFile=" << p.coreFile
            << " processArgs=" << p.processArgs.join(sep)
            << " environment=<" << p.environment.size() << " variables>"
            << " workingDir=" << p.workingDir << " buildDir=" << p.buildDir
            << " attachPID=" << p.attachPID << " useTerminal=" << p.useTerminal
            << " remoteChannel=" << p.remoteChannel
            << " remoteArchitecture=" << p.remoteArchitecture
185
            << " symbolFileName=" << p.symbolFileName
186
187
            << " serverStartScript=" << p.serverStartScript
            << " toolchain=" << p.toolChainType << '\n';
188
189
190
    return str;
}

191
using namespace Constants;
192
using namespace Debugger::Internal;
193
using namespace TextEditor;
con's avatar
con committed
194

195
const char *DebuggerManager::stateName(int s)
196
{
hjk's avatar
hjk committed
197
    #define SN(x) case x: return #x;
198
    switch (s) {
hjk's avatar
hjk committed
199
200
201
202
203
204
205
206
        SN(DebuggerNotReady)
        SN(EngineStarting)
        SN(AdapterStarting)
        SN(AdapterStarted)
        SN(AdapterStartFailed)
        SN(InferiorStarting)
        SN(InferiorStartFailed)
        SN(InferiorRunningRequested)
207
        SN(InferiorRunningRequested_Kill)
hjk's avatar
hjk committed
208
        SN(InferiorRunning)
209
        SN(InferiorUnrunnable)
hjk's avatar
hjk committed
210
        SN(InferiorStopping)
211
        SN(InferiorStopping_Kill)
hjk's avatar
hjk committed
212
213
214
215
216
        SN(InferiorStopped)
        SN(InferiorStopFailed)
        SN(InferiorShuttingDown)
        SN(InferiorShutDown)
        SN(InferiorShutdownFailed)
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
217
        SN(EngineShuttingDown)
218
219
    }
    return "<unknown>";
hjk's avatar
hjk committed
220
    #undef SN
221
222
}

con's avatar
con committed
223
224
225

///////////////////////////////////////////////////////////////////////
//
226
// DebuggerStartParameters
con's avatar
con committed
227
228
229
//
///////////////////////////////////////////////////////////////////////

230
231
DebuggerStartParameters::DebuggerStartParameters()
  : attachPID(-1),
232
    useTerminal(false),
hjk's avatar
hjk committed
233
234
    toolChainType(ProjectExplorer::ToolChain::UNKNOWN),
    startMode(NoStartMode)
235
{}
236
237
238

void DebuggerStartParameters::clear()
{
239
    *this = DebuggerStartParameters();
240
241
}

242
243
244
245
246
247
248

///////////////////////////////////////////////////////////////////////
//
// DebuggerManager
//
///////////////////////////////////////////////////////////////////////

249
250
static Debugger::Internal::IDebuggerEngine *gdbEngine = 0;
static Debugger::Internal::IDebuggerEngine *scriptEngine = 0;
hjk's avatar
hjk committed
251
252
static Debugger::Internal::IDebuggerEngine *cdbEngine = 0;
static Debugger::Internal::IDebuggerEngine *pdbEngine = 0;
253

254
255
struct DebuggerManagerPrivate
{
256
    explicit DebuggerManagerPrivate(DebuggerManager *manager);
257

258
259
    static DebuggerManager *instance;

con's avatar
con committed
260
261
    QIcon m_stopIcon;
    QIcon m_interruptIcon;
262
263
    const QIcon m_locationMarkIcon;

264
265
266
    // FIXME: Remove engine-specific state
    DebuggerStartParametersPtr m_startParameters;
    qint64 m_inferiorPid;
267

268
    /// Views
269
    DebuggerMainWindow *m_mainWindow;
270

271
    QLabel *m_statusLabel;
272

273
274
275
276
    QDockWidget *m_breakDock;
    QDockWidget *m_modulesDock;
    QDockWidget *m_outputDock;
    QDockWidget *m_registerDock;
277
    QDockWidget *m_snapshotDock;
278
    QDockWidget *m_sourceFilesDock;
279
    QDockWidget *m_stackDock;
280
281
    QDockWidget *m_threadsDock;
    QDockWidget *m_watchDock;
282
    QList<QDockWidget *> m_dockWidgets;
283
284
285
286

    BreakHandler *m_breakHandler;
    ModulesHandler *m_modulesHandler;
    RegisterHandler *m_registerHandler;
287
    SnapshotHandler *m_snapshotHandler;
288
289
290
291
292
293
294
295
296
297
    StackHandler *m_stackHandler;
    ThreadsHandler *m_threadsHandler;
    WatchHandler *m_watchHandler;

    DebuggerManagerActions m_actions;

    QWidget *m_breakWindow;
    QWidget *m_localsWindow;
    QWidget *m_registerWindow;
    QWidget *m_modulesWindow;
298
299
    QWidget *m_snapshotWindow;
    SourceFilesWindow *m_sourceFilesWindow;
300
301
302
303
304
305
306
307
    QWidget *m_stackWindow;
    QWidget *m_threadsWindow;
    QWidget *m_watchersWindow;
    DebuggerOutputWindow *m_outputWindow;

    bool m_busy;
    QTimer *m_statusTimer;
    QString m_lastPermanentStatusMessage;
308
    DisassemblerViewAgent m_disassemblerViewAgent;
309
310
311

    IDebuggerEngine *m_engine;
    DebuggerState m_state;
312
313

    CPlusPlus::Snapshot m_codeModelSnapshot;
314
    DebuggerPlugin *m_plugin;
315
316
};

317
318
DebuggerManager *DebuggerManagerPrivate::instance = 0;

319
DebuggerManagerPrivate::DebuggerManagerPrivate(DebuggerManager *manager) :
con's avatar
con committed
320
321
   m_stopIcon(QLatin1String(":/debugger/images/debugger_stop_small.png")),
   m_interruptIcon(QLatin1String(":/debugger/images/debugger_interrupt_small.png")),
con's avatar
con committed
322
   m_locationMarkIcon(QLatin1String(":/debugger/images/location_16.png")),
323
324
325
326
   m_startParameters(new DebuggerStartParameters),
   m_inferiorPid(0),
   m_disassemblerViewAgent(manager),
   m_engine(0)
327
{
con's avatar
con committed
328
329
    m_interruptIcon.addFile(":/debugger/images/debugger_interrupt.png");
    m_stopIcon.addFile(":/debugger/images/debugger_stop.png");
330
331
}

332
DebuggerManager::DebuggerManager(DebuggerPlugin *plugin)
333
  : d(new DebuggerManagerPrivate(this))
con's avatar
con committed
334
{
335
    DebuggerManagerPrivate::instance = this;
336
    d->m_plugin = plugin;
337
    init();
con's avatar
con committed
338
339
340
341
}

DebuggerManager::~DebuggerManager()
{
342
    #define doDelete(ptr) delete ptr; ptr = 0
343
344
345
346
347
348
349
350
351
352
353
354
355
    doDelete(scriptEngine);
    doDelete(pdbEngine);
    doDelete(gdbEngine);
    doDelete(cdbEngine);

    doDelete(d->m_breakHandler);
    doDelete(d->m_threadsHandler);
    doDelete(d->m_modulesHandler);
    doDelete(d->m_registerHandler);
    doDelete(d->m_snapshotHandler);
    doDelete(d->m_stackHandler);
    doDelete(d->m_watchHandler);

356
357
    doDelete(gdbEngine);
    doDelete(scriptEngine);
hjk's avatar
hjk committed
358
    doDelete(cdbEngine);
359
    #undef doDelete
360
    DebuggerManagerPrivate::instance = 0;
361
    delete d;
con's avatar
con committed
362
363
}

364
365
366
367
368
DebuggerManager *DebuggerManager::instance()
{
    return DebuggerManagerPrivate::instance;
}

369
void DebuggerManager::init()
con's avatar
con committed
370
{
371
372
    d->m_state = DebuggerState(-1);
    d->m_busy = false;
con's avatar
con committed
373

374
375
    d->m_modulesHandler = 0;
    d->m_registerHandler = 0;
con's avatar
con committed
376

377
378
    d->m_statusLabel = new QLabel;
    d->m_statusLabel->setMinimumSize(QSize(30, 10));
379

380
    d->m_breakWindow = new BreakWindow(this);
381
    d->m_breakWindow->setObjectName(QLatin1String("CppDebugBreakpoints"));
382
    d->m_modulesWindow = new ModulesWindow(this);
383
    d->m_modulesWindow->setObjectName(QLatin1String("CppDebugModules"));
384
    d->m_outputWindow = new DebuggerOutputWindow;
385
386
    d->m_outputWindow->setObjectName(QLatin1String("CppDebugOutput"));

387
    d->m_registerWindow = new RegisterWindow(this);
388
    d->m_registerWindow->setObjectName(QLatin1String("CppDebugRegisters"));
389
    d->m_snapshotWindow = new SnapshotWindow(this);
390
    d->m_snapshotWindow->setObjectName(QLatin1String("CppDebugSnapshots"));
391
    d->m_stackWindow = new StackWindow(this);
392
    d->m_stackWindow->setObjectName(QLatin1String("CppDebugStack"));
393
    d->m_sourceFilesWindow = new SourceFilesWindow;
394
    d->m_sourceFilesWindow->setObjectName(QLatin1String("CppDebugSources"));
395
    d->m_threadsWindow = new ThreadsWindow;
396
    d->m_threadsWindow->setObjectName(QLatin1String("CppDebugThreads"));
397
    d->m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this);
398
    d->m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
399
    d->m_watchersWindow = new WatchWindow(WatchWindow::WatchersType, this);
400
    d->m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
401
    d->m_statusTimer = new QTimer(this);
con's avatar
con committed
402

403
404
    d->m_mainWindow =
        qobject_cast<DebuggerMainWindow*>(DebuggerUISwitcher::instance()->mainWindow());
405
    QTC_ASSERT(d->m_mainWindow, return)
con's avatar
con committed
406

407
408
409
410
411
412
    // Snapshots
    d->m_snapshotHandler = new SnapshotHandler;
    QAbstractItemView *snapshotView =
        qobject_cast<QAbstractItemView *>(d->m_snapshotWindow);
    snapshotView->setModel(d->m_snapshotHandler);

con's avatar
con committed
413
    // Stack
414
    d->m_stackHandler = new StackHandler;
415
416
    StackWindow *stackView =
        qobject_cast<StackWindow *>(d->m_stackWindow);
417
    stackView->setModel(d->m_stackHandler->stackModel());
418
419
420
    stackView->header()->resizeSection(0, 60);
    stackView->header()->resizeSection(3, 60);

421
422
423
424
    connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
    connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
con's avatar
con committed
425
426

    // Threads
427
    d->m_threadsHandler = new ThreadsHandler;
con's avatar
con committed
428
    QAbstractItemView *threadsView =
429
430
        qobject_cast<QAbstractItemView *>(d->m_threadsWindow);
    threadsView->setModel(d->m_threadsHandler->threadsModel());
con's avatar
con committed
431
432
433
434
    connect(threadsView, SIGNAL(threadSelected(int)),
        this, SLOT(selectThread(int)));

    // Breakpoints
435
    d->m_breakHandler = new BreakHandler(this);
con's avatar
con committed
436
    QAbstractItemView *breakView =
437
438
        qobject_cast<QAbstractItemView *>(d->m_breakWindow);
    breakView->setModel(d->m_breakHandler->model());
439
    connect(breakView, SIGNAL(breakpointActivated(int)),
hjk's avatar
hjk committed
440
        this, SLOT(activateBreakpoint(int)));
441
    connect(breakView, SIGNAL(breakpointDeleted(int)),
442
        d->m_breakHandler, SLOT(removeBreakpoint(int)));
443
444
    connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
        this, SLOT(attemptBreakpointSynchronization()));
445
446
    connect(breakView, SIGNAL(breakByFunctionRequested(QString)),
        this, SLOT(breakByFunction(QString)), Qt::QueuedConnection);
447
448
    connect(breakView, SIGNAL(breakByFunctionMainRequested()),
        this, SLOT(breakByFunctionMain()), Qt::QueuedConnection);
con's avatar
con committed
449
450
451

    // Modules
    QAbstractItemView *modulesView =
452
453
454
        qobject_cast<QAbstractItemView *>(d->m_modulesWindow);
    d->m_modulesHandler = new ModulesHandler;
    modulesView->setModel(d->m_modulesHandler->model());
con's avatar
con committed
455
456
457
458
459
460
    connect(modulesView, SIGNAL(reloadModulesRequested()),
        this, SLOT(reloadModules()));
    connect(modulesView, SIGNAL(loadSymbolsRequested(QString)),
        this, SLOT(loadSymbols(QString)));
    connect(modulesView, SIGNAL(loadAllSymbolsRequested()),
        this, SLOT(loadAllSymbols()));
461
462
    connect(modulesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
hjk's avatar
hjk committed
463
464
    connect(modulesView, SIGNAL(newDockRequested(QWidget*)),
        this, SLOT(createNewDock(QWidget*)));
con's avatar
con committed
465

466
    // Source Files
467
    //d->m_sourceFilesHandler = new SourceFilesHandler;
468
    QAbstractItemView *sourceFilesView =
469
470
        qobject_cast<QAbstractItemView *>(d->m_sourceFilesWindow);
    //sourceFileView->setModel(d->m_stackHandler->stackModel());
471
472
    connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()),
        this, SLOT(reloadSourceFiles()));
473
474
    connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
con's avatar
con committed
475

476
    // Registers
con's avatar
con committed
477
    QAbstractItemView *registerView =
478
479
480
        qobject_cast<QAbstractItemView *>(d->m_registerWindow);
    d->m_registerHandler = new RegisterHandler;
    registerView->setModel(d->m_registerHandler->model());
con's avatar
con committed
481

482
    // Locals
483
    d->m_watchHandler = new WatchHandler(this);
484
485
    QTreeView *localsView = qobject_cast<QTreeView *>(d->m_localsWindow);
    localsView->setModel(d->m_watchHandler->model(LocalsWatch));
486
487

    // Watchers
488
489
    QTreeView *watchersView = qobject_cast<QTreeView *>(d->m_watchersWindow);
    watchersView->setModel(d->m_watchHandler->model(WatchersWatch));
490
    connect(theDebuggerAction(AssignValue), SIGNAL(triggered()),
491
        this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
492
493
    connect(theDebuggerAction(RemoveWatchExpression), SIGNAL(triggered()),
        this, SLOT(updateWatchersWindow()), Qt::QueuedConnection);
494
495
    connect(localsView->header(), SIGNAL(sectionResized(int,int,int)),
        this, SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
con's avatar
con committed
496

497
498
499
500
501
502
    // Log
    connect(this, SIGNAL(emitShowInput(int, QString)),
            d->m_outputWindow, SLOT(showInput(int, QString)), Qt::QueuedConnection);
    connect(this, SIGNAL(emitShowOutput(int, QString)),
            d->m_outputWindow, SLOT(showOutput(int, QString)), Qt::QueuedConnection);

con's avatar
con committed
503
    // Tooltip
504
505
    //QTreeView *tooltipView = qobject_cast<QTreeView *>(d->m_tooltipWindow);
    //tooltipView->setModel(d->m_watchHandler->model(TooltipsWatch));
506
    qRegisterMetaType<WatchData>("WatchData");
hjk's avatar
hjk committed
507
    qRegisterMetaType<StackCookie>("StackCookie");
508

509
    d->m_actions.continueAction = new QAction(tr("Continue"), this);
con's avatar
con committed
510
511
512
    QIcon continueIcon = QIcon(":/debugger/images/debugger_continue_small.png");
    continueIcon.addFile(":/debugger/images/debugger_continue.png");
    d->m_actions.continueAction->setIcon(continueIcon);
con's avatar
con committed
513

514
    d->m_actions.stopAction = new QAction(tr("Interrupt"), this);
con's avatar
con committed
515
    d->m_actions.stopAction->setIcon(d->m_interruptIcon);
con's avatar
con committed
516

517
518
519
    d->m_actions.resetAction = new QAction(tr("Abort Debugging"), this);
    d->m_actions.resetAction->setToolTip(tr("Aborts debugging and "
        "resets the debugger to the initial state."));
con's avatar
con committed
520

521
    d->m_actions.nextAction = new QAction(tr("Step Over"), this);
hjk's avatar
hjk committed
522
523
    d->m_actions.nextAction->setIcon(
        QIcon(":/debugger/images/debugger_stepover_small.png"));
con's avatar
con committed
524

525
    d->m_actions.stepAction = new QAction(tr("Step Into"), this);
hjk's avatar
hjk committed
526
527
    d->m_actions.stepAction->setIcon(
        QIcon(":/debugger/images/debugger_stepinto_small.png"));
con's avatar
con committed
528

529
    d->m_actions.stepOutAction = new QAction(tr("Step Out"), this);
hjk's avatar
hjk committed
530
531
    d->m_actions.stepOutAction->setIcon(
        QIcon(":/debugger/images/debugger_stepout_small.png"));
con's avatar
con committed
532

533
534
    d->m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this);
    d->m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this);
con's avatar
con committed
535

536
537
538
539
540
    d->m_actions.runToFunctionAction =
        new QAction(tr("Run to Outermost Function"), this);

    d->m_actions.returnFromFunctionAction =
        new QAction(tr("Immediately Return From Inner Function"), this);
con's avatar
con committed
541

542
543
    d->m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this);
    d->m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this);
con's avatar
con committed
544

545
    d->m_actions.breakAction = new QAction(tr("Toggle Breakpoint"), this);
con's avatar
con committed
546

547
548
    d->m_actions.watchAction1 = new QAction(tr("Add to Watch Window"), this);
    d->m_actions.watchAction2 = new QAction(tr("Add to Watch Window"), this);
con's avatar
con committed
549

550
    d->m_actions.snapshotAction = new QAction(tr("Snapshot"), this);
hjk's avatar
hjk committed
551
552
    d->m_actions.snapshotAction->setIcon(
        QIcon(":/debugger/images/debugger_snapshot_small.png"));
553

hjk's avatar
hjk committed
554
555
    d->m_actions.reverseDirectionAction =
        new QAction(tr("Reverse Direction"), this);
556
557
    d->m_actions.reverseDirectionAction->setCheckable(true);
    d->m_actions.reverseDirectionAction->setChecked(false);
hjk's avatar
hjk committed
558
    d->m_actions.reverseDirectionAction->setIcon(
hjk's avatar
hjk committed
559
        QIcon(":/debugger/images/debugger_reversemode_16.png"));
560
    d->m_actions.reverseDirectionAction->setIconVisibleInMenu(false);
561

562
    connect(d->m_actions.continueAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
563
        this, SLOT(executeContinue()));
564
    connect(d->m_actions.stopAction, SIGNAL(triggered()),
con's avatar
con committed
565
        this, SLOT(interruptDebuggingRequest()));
566
    connect(d->m_actions.resetAction, SIGNAL(triggered()),
567
        this, SLOT(abortDebugger()));
568
    connect(d->m_actions.nextAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
569
        this, SLOT(executeStepNext()));
570
    connect(d->m_actions.stepAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
571
        this, SLOT(executeStep()));
572
    connect(d->m_actions.stepOutAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
573
        this, SLOT(executeStepOut()));
574
    connect(d->m_actions.runToLineAction1, SIGNAL(triggered()),
hjk's avatar
hjk committed
575
        this, SLOT(executeRunToLine()));
576
    connect(d->m_actions.runToLineAction2, SIGNAL(triggered()),
hjk's avatar
hjk committed
577
        this, SLOT(executeRunToLine()));
578
    connect(d->m_actions.runToFunctionAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
579
        this, SLOT(executeRunToFunction()));
580
    connect(d->m_actions.jumpToLineAction1, SIGNAL(triggered()),
hjk's avatar
hjk committed
581
        this, SLOT(executeJumpToLine()));
582
    connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()),
hjk's avatar
hjk committed
583
        this, SLOT(executeJumpToLine()));
584
    connect(d->m_actions.returnFromFunctionAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
585
        this, SLOT(executeReturn()));
586
587
588
    connect(d->m_actions.watchAction1, SIGNAL(triggered()),
        this, SLOT(addToWatchWindow()));
    connect(d->m_actions.watchAction2, SIGNAL(triggered()),
con's avatar
con committed
589
        this, SLOT(addToWatchWindow()));
590
591
    connect(d->m_actions.snapshotAction, SIGNAL(triggered()),
        this, SLOT(makeSnapshot()));
con's avatar
con committed
592

593
    connect(d->m_statusTimer, SIGNAL(timeout()),
594
        this, SLOT(clearStatusMessage()));
con's avatar
con committed
595

596
597
    connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
        this, SLOT(executeDebuggerCommand()));
598

599
600
    connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()),
        this, SLOT(watchPoint()));
con's avatar
con committed
601

602
603
    connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
        this, SLOT(operateByInstructionTriggered()));
604

605
606
607
    DebuggerUISwitcher *uiSwitcher = DebuggerUISwitcher::instance();
    d->m_breakDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_breakWindow);
    d->m_modulesDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_modulesWindow,
hjk's avatar
hjk committed
608
                                                    Qt::TopDockWidgetArea, false);
609

610
    connect(d->m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
611
612
        this, SLOT(reloadModules()), Qt::QueuedConnection);

613
    d->m_registerDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_registerWindow,
614
        Qt::TopDockWidgetArea, false);
615
    connect(d->m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
616
617
        this, SLOT(reloadRegisters()), Qt::QueuedConnection);

618
    d->m_outputDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_outputWindow,
619
        Qt::TopDockWidgetArea, false);
620

621
622
    d->m_snapshotDock =  uiSwitcher->createDockWidget(LANG_CPP, d->m_snapshotWindow);
    d->m_stackDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_stackWindow);
623
624
    d->m_sourceFilesDock = uiSwitcher->createDockWidget(LANG_CPP,
        d->m_sourceFilesWindow, Qt::TopDockWidgetArea, false);
625
    connect(d->m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
626
627
        this, SLOT(reloadSourceFiles()), Qt::QueuedConnection);

628
    d->m_threadsDock = uiSwitcher->createDockWidget(LANG_CPP, d->m_threadsWindow);
con's avatar
con committed
629

630
    QSplitter *localsAndWatchers = new Core::MiniSplitter(Qt::Vertical);
631
    localsAndWatchers->setObjectName(QLatin1String("CppDebugLocalsAndWatchers"));
632
633
634
635
    localsAndWatchers->setWindowTitle(d->m_localsWindow->windowTitle());
    localsAndWatchers->addWidget(d->m_localsWindow);
    localsAndWatchers->addWidget(d->m_watchersWindow);
    //localsAndWatchers->addWidget(d->m_tooltipWindow);
636
637
    localsAndWatchers->setStretchFactor(0, 3);
    localsAndWatchers->setStretchFactor(1, 1);
638
    localsAndWatchers->setStretchFactor(2, 1);
639
640
    d->m_watchDock = DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP,
        localsAndWatchers);
641
642
643
    d->m_dockWidgets << d->m_breakDock << d->m_modulesDock << d->m_registerDock
                     << d->m_outputDock << d->m_stackDock << d->m_sourceFilesDock
                     << d->m_threadsDock << d->m_watchDock;
644

hjk's avatar
hjk committed
645
    setState(DebuggerNotReady);
646
647
}

648
QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
649
650
{
    QList<Core::IOptionsPage*> rc;
651

652
653
654
655
    if (enabledTypeFlags & GdbEngineType) {
        gdbEngine = createGdbEngine(this);
        gdbEngine->addOptionPages(&rc);
    }
656

hjk's avatar
hjk committed
657
    cdbEngine = createCdbEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
658
659
660
661
662
663

    if (enabledTypeFlags & ScriptEngineType) {
        scriptEngine = createScriptEngine(this);
        scriptEngine->addOptionPages(&rc);
    }

hjk's avatar
hjk committed
664
665
666
    if (enabledTypeFlags & PdbEngineType) {
        pdbEngine = createPdbEngine(this);
        //pdbEngine->addOptionPages(&rc);
hjk's avatar
hjk committed
667
668
    }

669
    d->m_engine = 0;
hjk's avatar
hjk committed
670
671
    STATE_DEBUG(gdbEngine << cdbEngine << scriptEngine
        << pdbEngine << rc.size());
672
    return rc;
con's avatar
con committed
673
674
}

675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
DebuggerManagerActions DebuggerManager::debuggerManagerActions() const
{
    return d->m_actions;
}

QLabel *DebuggerManager::statusLabel() const
{
    return d->m_statusLabel;
}

IDebuggerEngine *DebuggerManager::currentEngine() const
{
    return d->m_engine;
}

ModulesHandler *DebuggerManager::modulesHandler() const
{
    return d->m_modulesHandler;
}

BreakHandler *DebuggerManager::breakHandler() const
{
    return d->m_breakHandler;
}

RegisterHandler *DebuggerManager::registerHandler() const
{
    return d->m_registerHandler;
}

StackHandler *DebuggerManager::stackHandler() const
{
    return d->m_stackHandler;
}

ThreadsHandler *DebuggerManager::threadsHandler() const
{
    return d->m_threadsHandler;
}

WatchHandler *DebuggerManager::watchHandler() const
{
    return d->m_watchHandler;
}

720
721
722
723
724
SnapshotHandler *DebuggerManager::snapshotHandler() const
{
    return d->m_snapshotHandler;
}

725
726
727
728
729
730
731
732
733
const CPlusPlus::Snapshot &DebuggerManager::cppCodeModelSnapshot() const
{
    if (d->m_codeModelSnapshot.isEmpty() && theDebuggerAction(UseCodeModel)->isChecked())
        d->m_codeModelSnapshot = CppTools::CppModelManagerInterface::instance()->snapshot();
    return d->m_codeModelSnapshot;
}

void DebuggerManager::clearCppCodeModelSnapshot()
{
734
    d->m_codeModelSnapshot = CPlusPlus::Snapshot();
735
736
}

737
738
739
740
741
742
SourceFilesWindow *DebuggerManager::sourceFileWindow() const
{
    return d->m_sourceFilesWindow;
}

QWidget *DebuggerManager::threadsWindow() const
con's avatar
con committed
743
{
744
    return d->m_threadsWindow;
con's avatar
con committed
745
746
}

hjk's avatar
hjk committed
747
748
void DebuggerManager::createNewDock(QWidget *widget)
{
749
750
    QDockWidget *dockWidget =
        DebuggerUISwitcher::instance()->createDockWidget(LANG_CPP, widget);
751
    dockWidget->setWindowTitle(widget->windowTitle());
hjk's avatar
hjk committed
752
753
    dockWidget->setObjectName(widget->windowTitle());
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
754
755
    //dockWidget->setWidget(widget);
    //d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
hjk's avatar
hjk committed
756
757
758
    dockWidget->show();
}

759
void DebuggerManager::setSimpleDockWidgetArrangement(const QString &activeLanguage)
con's avatar
con committed
760
{
hjk's avatar
hjk committed
761
    if (activeLanguage == LANG_CPP || activeLanguage.isEmpty()) {
762
763
764
765
766
767
768
769
        d->m_mainWindow->setTrackingEnabled(false);
        QList<QDockWidget *> dockWidgets = d->m_mainWindow->dockWidgets();
        foreach (QDockWidget *dockWidget, dockWidgets) {
            if (d->m_dockWidgets.contains(dockWidget)) {
                dockWidget->setFloating(false);
                d->m_mainWindow->removeDockWidget(dockWidget);
            }
        }
con's avatar
con committed
770

771
772
773
774
775
776
777
778
779
        foreach (QDockWidget *dockWidget, dockWidgets) {
            if (d->m_dockWidgets.contains(dockWidget)) {
                if (dockWidget == d->m_outputDock)
                    d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
                else
                    d->m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
                dockWidget->show();
            }
        }
con's avatar
con committed
780

781
782
783
784
785
786
787
788
789
790
791
792
793
794
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_breakDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_modulesDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_registerDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_threadsDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_sourceFilesDock);
        d->m_mainWindow->tabifyDockWidget(d->m_watchDock, d->m_snapshotDock);
        // They following views are rarely used in ordinary debugging. Hiding them
        // saves cycles since the corresponding information won't be retrieved.
        d->m_sourceFilesDock->hide();
        d->m_registerDock->hide();
        d->m_modulesDock->hide();
        d->m_outputDock->hide();
        d->m_mainWindow->setTrackingEnabled(true);
    }
con's avatar
con committed
795
796
797
798
}

QAbstractItemModel *DebuggerManager::threadsModel()
{
799
    return qobject_cast<ThreadsWindow*>(d->m_threadsWindow)->model();
con's avatar
con committed
800
801
}

802
803
void DebuggerManager::clearStatusMessage()
{
804
    d->m_statusLabel->setText(d->m_lastPermanentStatusMessage);
805
806
}

807
void DebuggerManager::showStatusMessage(const QString &msg0, int timeout)
con's avatar
con committed
808
809
{
    Q_UNUSED(timeout)
810
811
812
    showDebuggerOutput(LogStatus, msg0);
    QString msg = msg0;
    msg.replace(QLatin1Char('\n'), QString());
813
    d->m_statusLabel->setText(msg);
814
    if (timeout > 0) {
815
816
        d->m_statusTimer->setSingleShot(true);
        d->m_statusTimer->start(timeout);
817
    } else {
818
819
        d->m_lastPermanentStatusMessage = msg;
        d->m_statusTimer->stop();
820
    }
con's avatar
con committed
821
822
823
824
}

void DebuggerManager::notifyInferiorStopped()
{
hjk's avatar
hjk committed
825
    setState(InferiorStopped);
826
    showStatusMessage(tr("Stopped"), 5000);
con's avatar
con committed
827
828
829
830
}

void DebuggerManager::notifyInferiorRunning()
{
hjk's avatar
hjk committed
831
    setState(InferiorRunning);
con's avatar
con committed
832
833
834
835
836
    showStatusMessage(tr("Running..."), 5000);
}

void DebuggerManager::notifyInferiorExited()
{
hjk's avatar
hjk committed
837
    setState(DebuggerNotReady);
838
    showStatusMessage(tr("Exited"), 5000);
con's avatar
con committed
839
840
}

841
void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
con's avatar
con committed
842
{
843
    STATE_DEBUG(d->m_inferiorPid << pid);
844

845
846
    if (d->m_inferiorPid != pid) {
        d->m_inferiorPid = pid;
847
848
        emit inferiorPidChanged(pid);
    }
con's avatar
con committed
849
850
}

851
void DebuggerManager::showApplicationOutput(const QString &str, bool onStdErr)
con's avatar
con committed
852
{
853
     emit applicationOutputAvailable(str, onStdErr);
con's avatar
con committed
854
855
}

856
void DebuggerManager::aboutToShutdown()
con's avatar
con committed
857
{
858
859
860
861
    STATE_DEBUG(d->m_engine);
    if (d->m_engine)
        d->m_engine->shutdown();
    d->m_engine = 0;
con's avatar
con committed
862
863
}

864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
void DebuggerManager::makeSnapshot()
{
    QTC_ASSERT(d->m_engine, return);
    d->m_engine->makeSnapshot();
}

void DebuggerManager::activateSnapshot(int index)
{
    QTC_ASSERT(d->m_engine, return);
    d->m_engine->activateSnapshot(index);
}

void DebuggerManager::removeSnapshot(int index)
{
    QTC_ASSERT(d->m_engine, return);
    d->m_snapshotHandler->removeSnapshot(index);
}

882
883
BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lineNumber)
{
884
    if (!d->m_breakHandler)
885
        return 0;
886
887
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
    return index == -1 ? 0 : d->m_breakHandler->at(index);
888
889
}

890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
// FIXME: move further up the plugin where there's more specific context
// information available.
static BreakpointData *createBreakpointByFileAndLine
    (const QString &fileName, int lineNumber, BreakHandler *handler)
{
    BreakpointData *data = new BreakpointData(handler);
    if (lineNumber > 0) {
        data->fileName = fileName;
        data->lineNumber = QByteArray::number(lineNumber);
        data->pending = true;
        data->setMarkerFileName(fileName);
        data->setMarkerLineNumber(lineNumber);
    } else {
        data->funcName = fileName;
        data->lineNumber = 0;
        data->pending = true;
        // FIXME: Figure out in which disassembler view the Marker sits.
        // Might be better to let the user code create the BreakpointData
        // structure and insert it here.
        data->setMarkerFileName(QString());
        data->setMarkerLineNumber(0);
    }
    return data;
}

con's avatar
con committed
915
916
void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
917
    STATE_DEBUG(fileName << lineNumber);
918
    QTC_ASSERT(d->m_breakHandler, return);
hjk's avatar
hjk committed
919
920
921
    if (state() != InferiorRunning
         && state() != InferiorStopped
         && state() != DebuggerNotReady) {
922
923
924
925
926
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

927
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
con's avatar
con committed
928
    if (index == -1)
929
930
        d->m_breakHandler->appendBreakpoint(
            createBreakpointByFileAndLine(fileName, lineNumber, d->m_breakHandler));
con's avatar
con committed
931
    else
932
        d->m_breakHandler->removeBreakpoint(index);
933

hjk's avatar
hjk committed
934
    attemptBreakpointSynchronization();
con's avatar
con committed
935
936
}