debuggermanager.cpp 53.6 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
5
** Copyright (c) 2009 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 "debuggeractions.h"
33
#include "debuggeragents.h"
34
#include "debuggerrunner.h"
con's avatar
con committed
35
36
#include "debuggerconstants.h"
#include "idebuggerengine.h"
37
#include "debuggerstringutils.h"
con's avatar
con committed
38
39
40
41
42
43

#include "breakwindow.h"
#include "debuggeroutputwindow.h"
#include "moduleswindow.h"
#include "registerwindow.h"
#include "stackwindow.h"
44
#include "sourcefileswindow.h"
con's avatar
con committed
45
46
47
#include "threadswindow.h"
#include "watchwindow.h"

48

con's avatar
con committed
49
50
51
52
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "stackhandler.h"
53
#include "stackframe.h"
con's avatar
con committed
54
55
#include "watchhandler.h"

56
#include "debuggerdialogs.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
57
#ifdef Q_OS_WIN
58
#  include "shared/peutils.h"
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
59
#endif
60
#include <coreplugin/icore.h>
61
#include <utils/qtcassert.h>
62
#include <utils/fancymainwindow.h>
63
#include <projectexplorer/toolchain.h>
64

con's avatar
con committed
65
66
67
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
68
#include <QtCore/QTextStream>
con's avatar
con committed
69
#include <QtCore/QTime>
70
#include <QtCore/QTimer>
con's avatar
con committed
71

72
#include <QtGui/QApplication>
con's avatar
con committed
73
74
75
76
77
78
79
80
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
#include <QtGui/QErrorMessage>
#include <QtGui/QFileDialog>
#include <QtGui/QLabel>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
81
#include <QtGui/QPushButton>
con's avatar
con committed
82
83
84
85
86
87
#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolButton>
#include <QtGui/QToolTip>

88
89
90
91
92
93
94
95
96
97
#define DEBUG_STATE 1
#ifdef DEBUG_STATE
// use  Q_FUNC_INFO?
#   define STATE_DEBUG(s) \
    { QString msg; QTextStream ts(&msg); ts << s; \
      showDebuggerOutput(LogDebug, msg); }
#else
#   define STATE_DEBUG(s)
#endif

98
99
// 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
100
101
// whereas the debugged process is referred to as 'Inferior'.
//
hjk's avatar
hjk committed
102
103
104
105
106
107
108
109
110
111
112
113
114
115
//               0 == DebuggerNotReady
//                          |
//                     EngineStarting
//                          |
//                     AdapterStarting --> AdapterStartFailed --> 0
//                          |
//                     AdapterStarted
//                          |
//                     InferiorPreparing --> InferiorPreparationFailed --> 0
//                          |
//                     InferiorPrepared
//                          |
//                     InferiorStarting --> InferiorStartFailed --> 0
//                          |
116
117
118
119
//         (core)           |     (attach) (remote)
//      .-----------------<-|->--------------------.
//      |                   v                      |
//  InferiorUnrunnable      |                      |
hjk's avatar
hjk committed
120
//      |                   |                      v
121
122
//      |                   | (plain)
//      |                   | (trk)
hjk's avatar
hjk committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//      |                   |
//      |                   |  .------------------------------------.
//      |                   |  v                                    |
//      |              InferiorRunningRequested    v                |
//      |                   |                      |                |
//      |        .---- InferiorRunning             |                |
//      |        |          |                      |                |
//      |        |     InferiorStopping            |                |
//      |        |          |                      |                |
//      |        v          v                      |                |
//      |        |<--- InferiorStopped <-----------'                |
//      |        |          |                                       |
//      |        |          `---------------------------------------'
//      |        |          
//      |        '---> InferiorShuttingDown  -> InferiorShutdownFailed
//      |                   |
//      |              InferiorShutDown
//      |                   |
//      |                   v
//      '------------> AdapterShuttingDown  -> AdapterShutdownFailed --> 0
//                          |
//                          0
hjk's avatar
hjk committed
145
146
147
148
149
150
//
// Allowed actions:
//    [R] :  Run
//    [C] :  Continue
//    [N] :  Step, Next

151
152
namespace Debugger {
namespace Internal {
153

154
155
156
157
158
159
160
161
IDebuggerEngine *createGdbEngine(DebuggerManager *parent);
IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
IDebuggerEngine *createTcfEngine(DebuggerManager *parent);

// The createWinEngine 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.
162
163
164
165
166
167
168

IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
169

170
} // namespace Internal
171

172
DEBUGGER_EXPORT QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
173
174
175
176
177
178
179
180
181
182
{
    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
183
            << " symbolFileName=" << p.symbolFileName
184
185
            << " serverStartScript=" << p.serverStartScript
            << " toolchain=" << p.toolChainType << '\n';
186
187
188
    return str;
}

189
using namespace Constants;
190
using namespace Debugger::Internal;
con's avatar
con committed
191
192
193

static const QString tooltipIName = "tooltip";

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

con's avatar
con committed
224
225
226

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

231
232
DebuggerStartParameters::DebuggerStartParameters()
  : attachPID(-1),
233
    useTerminal(false),
hjk's avatar
hjk committed
234
235
    toolChainType(ProjectExplorer::ToolChain::UNKNOWN),
    startMode(NoStartMode)
236
{}
237
238
239
240
241
242
243
244
245
246
247

void DebuggerStartParameters::clear()
{
    executable.clear();
    coreFile.clear();
    processArgs.clear();
    environment.clear();
    workingDir.clear();
    buildDir.clear();
    attachPID = -1;
    useTerminal = false;
248
    crashParameter.clear();
249
250
251
    remoteChannel.clear();
    remoteArchitecture.clear();
    serverStartScript.clear();
252
    toolChainType = ProjectExplorer::ToolChain::UNKNOWN;
hjk's avatar
hjk committed
253
    startMode = NoStartMode;
254
255
}

256
257
258
259
260
261
262

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

263
264
265
266
static Debugger::Internal::IDebuggerEngine *gdbEngine = 0;
static Debugger::Internal::IDebuggerEngine *scriptEngine = 0;
static Debugger::Internal::IDebuggerEngine *tcfEngine = 0;
static Debugger::Internal::IDebuggerEngine *winEngine = 0;
267

268
269
270
struct DebuggerManagerPrivate
{
    DebuggerManagerPrivate(DebuggerManager *manager);
271

272
273
    static DebuggerManager *instance;

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    // FIXME: Remove engine-specific state
    DebuggerStartParametersPtr m_startParameters;
    qint64 m_inferiorPid;
    /// Views
    Core::Utils::FancyMainWindow *m_mainWindow;
    QLabel *m_statusLabel;
    QDockWidget *m_breakDock;
    QDockWidget *m_modulesDock;
    QDockWidget *m_outputDock;
    QDockWidget *m_registerDock;
    QDockWidget *m_stackDock;
    QDockWidget *m_sourceFilesDock;
    QDockWidget *m_threadsDock;
    QDockWidget *m_watchDock;

    BreakHandler *m_breakHandler;
    ModulesHandler *m_modulesHandler;
    RegisterHandler *m_registerHandler;
    StackHandler *m_stackHandler;
    ThreadsHandler *m_threadsHandler;
    WatchHandler *m_watchHandler;
    SourceFilesWindow *m_sourceFilesWindow;

    DebuggerManagerActions m_actions;

    QWidget *m_breakWindow;
    QWidget *m_localsWindow;
    QWidget *m_registerWindow;
    QWidget *m_modulesWindow;
    QWidget *m_stackWindow;
    QWidget *m_threadsWindow;
    QWidget *m_watchersWindow;
    DebuggerOutputWindow *m_outputWindow;

    bool m_busy;
    QTimer *m_statusTimer;
    QString m_lastPermanentStatusMessage;
311
    DisassemblerViewAgent m_disassemblerViewAgent;
312
313
314
315
316

    IDebuggerEngine *m_engine;
    DebuggerState m_state;
};

317
318
DebuggerManager *DebuggerManagerPrivate::instance = 0;

319
320
321
DebuggerManagerPrivate::DebuggerManagerPrivate(DebuggerManager *manager)
  : m_startParameters(new DebuggerStartParameters),
    m_disassemblerViewAgent(manager)
322
{
323
    m_inferiorPid = 0;
324
325
}

326
327
DebuggerManager::DebuggerManager()
  : d(new DebuggerManagerPrivate(this))
con's avatar
con committed
328
{
329
    DebuggerManagerPrivate::instance = this;
330
    init();
con's avatar
con committed
331
332
333
334
}

DebuggerManager::~DebuggerManager()
{
335
336
337
338
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(gdbEngine);
    doDelete(scriptEngine);
    doDelete(tcfEngine);
hjk's avatar
hjk committed
339
    doDelete(winEngine);
340
    #undef doDelete
341
    DebuggerManagerPrivate::instance = 0;
342
    delete d;
con's avatar
con committed
343
344
}

345
346
347
348
349
DebuggerManager *DebuggerManager::instance()
{
    return DebuggerManagerPrivate::instance;
}

350
void DebuggerManager::init()
con's avatar
con committed
351
{
352
353
    d->m_state = DebuggerState(-1);
    d->m_busy = false;
con's avatar
con committed
354

355
356
    d->m_modulesHandler = 0;
    d->m_registerHandler = 0;
con's avatar
con committed
357

358
359
    d->m_statusLabel = new QLabel;
    d->m_statusLabel->setMinimumSize(QSize(30, 10));
360

361
362
363
364
365
366
367
368
369
370
    d->m_breakWindow = new BreakWindow;
    d->m_modulesWindow = new ModulesWindow(this);
    d->m_outputWindow = new DebuggerOutputWindow;
    d->m_registerWindow = new RegisterWindow(this);
    d->m_stackWindow = new StackWindow(this);
    d->m_sourceFilesWindow = new SourceFilesWindow;
    d->m_threadsWindow = new ThreadsWindow;
    d->m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this);
    d->m_watchersWindow = new WatchWindow(WatchWindow::WatchersType, this);
    d->m_statusTimer = new QTimer(this);
con's avatar
con committed
371

372
373
374
    d->m_mainWindow = new Core::Utils::FancyMainWindow;
    d->m_mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North);
    d->m_mainWindow->setDocumentMode(true);
con's avatar
con committed
375
376

    // Stack
377
    d->m_stackHandler = new StackHandler;
con's avatar
con committed
378
    QAbstractItemView *stackView =
379
380
        qobject_cast<QAbstractItemView *>(d->m_stackWindow);
    stackView->setModel(d->m_stackHandler->stackModel());
con's avatar
con committed
381
382
    connect(stackView, SIGNAL(frameActivated(int)),
        this, SLOT(activateFrame(int)));
383
384
385
386
    connect(theDebuggerAction(ExpandStack), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
    connect(theDebuggerAction(MaximalStackDepth), SIGNAL(triggered()),
        this, SLOT(reloadFullStack()));
con's avatar
con committed
387
388

    // Threads
389
    d->m_threadsHandler = new ThreadsHandler;
con's avatar
con committed
390
    QAbstractItemView *threadsView =
391
392
        qobject_cast<QAbstractItemView *>(d->m_threadsWindow);
    threadsView->setModel(d->m_threadsHandler->threadsModel());
con's avatar
con committed
393
394
395
396
    connect(threadsView, SIGNAL(threadSelected(int)),
        this, SLOT(selectThread(int)));

    // Breakpoints
397
    d->m_breakHandler = new BreakHandler(this);
con's avatar
con committed
398
    QAbstractItemView *breakView =
399
400
        qobject_cast<QAbstractItemView *>(d->m_breakWindow);
    breakView->setModel(d->m_breakHandler->model());
401
    connect(breakView, SIGNAL(breakpointActivated(int)),
402
        d->m_breakHandler, SLOT(activateBreakpoint(int)));
403
    connect(breakView, SIGNAL(breakpointDeleted(int)),
404
        d->m_breakHandler, SLOT(removeBreakpoint(int)));
405
406
    connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
        this, SLOT(attemptBreakpointSynchronization()));
407
408
    connect(breakView, SIGNAL(breakByFunctionRequested(QString)),
        this, SLOT(breakByFunction(QString)), Qt::QueuedConnection);
409
410
    connect(breakView, SIGNAL(breakByFunctionMainRequested()),
        this, SLOT(breakByFunctionMain()), Qt::QueuedConnection);
con's avatar
con committed
411
412
413

    // Modules
    QAbstractItemView *modulesView =
414
415
416
        qobject_cast<QAbstractItemView *>(d->m_modulesWindow);
    d->m_modulesHandler = new ModulesHandler;
    modulesView->setModel(d->m_modulesHandler->model());
con's avatar
con committed
417
418
419
420
421
422
    connect(modulesView, SIGNAL(reloadModulesRequested()),
        this, SLOT(reloadModules()));
    connect(modulesView, SIGNAL(loadSymbolsRequested(QString)),
        this, SLOT(loadSymbols(QString)));
    connect(modulesView, SIGNAL(loadAllSymbolsRequested()),
        this, SLOT(loadAllSymbols()));
423
424
    connect(modulesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
hjk's avatar
hjk committed
425
426
    connect(modulesView, SIGNAL(newDockRequested(QWidget*)),
        this, SLOT(createNewDock(QWidget*)));
con's avatar
con committed
427

428
    // Source Files
429
    //d->m_sourceFilesHandler = new SourceFilesHandler;
430
    QAbstractItemView *sourceFilesView =
431
432
        qobject_cast<QAbstractItemView *>(d->m_sourceFilesWindow);
    //sourceFileView->setModel(d->m_stackHandler->stackModel());
433
434
    connect(sourceFilesView, SIGNAL(reloadSourceFilesRequested()),
        this, SLOT(reloadSourceFiles()));
435
436
    connect(sourceFilesView, SIGNAL(fileOpenRequested(QString)),
        this, SLOT(fileOpen(QString)));
con's avatar
con committed
437

438
    // Registers
con's avatar
con committed
439
    QAbstractItemView *registerView =
440
441
442
        qobject_cast<QAbstractItemView *>(d->m_registerWindow);
    d->m_registerHandler = new RegisterHandler;
    registerView->setModel(d->m_registerHandler->model());
con's avatar
con committed
443

444
    // Locals
445
446
447
    d->m_watchHandler = new WatchHandler;
    QTreeView *localsView = qobject_cast<QTreeView *>(d->m_localsWindow);
    localsView->setModel(d->m_watchHandler->model(LocalsWatch));
448
449

    // Watchers
450
451
452
    QTreeView *watchersView = qobject_cast<QTreeView *>(d->m_watchersWindow);
    watchersView->setModel(d->m_watchHandler->model(WatchersWatch));
    connect(d->m_watchHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
hjk's avatar
hjk committed
453
        this, SIGNAL(sessionValueRequested(QString,QVariant*)));
454
    connect(d->m_watchHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
hjk's avatar
hjk committed
455
        this, SIGNAL(setSessionValueRequested(QString,QVariant)));
456
    connect(theDebuggerAction(AssignValue), SIGNAL(triggered()),
457
        this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
con's avatar
con committed
458
459

    // Tooltip
460
461
    //QTreeView *tooltipView = qobject_cast<QTreeView *>(d->m_tooltipWindow);
    //tooltipView->setModel(d->m_watchHandler->model(TooltipsWatch));
462
    //qRegisterMetaType<WatchData>("WatchData");
463
    qRegisterMetaType<WatchData>("WatchData");
464
465
    connect(d->m_watchHandler, SIGNAL(watchDataUpdateNeeded(Debugger::Internal::WatchData)),
            this, SLOT(updateWatchData(Debugger::Internal::WatchData)));
466

467
468
    d->m_actions.continueAction = new QAction(tr("Continue"), this);
    d->m_actions.continueAction->setIcon(QIcon(":/debugger/images/debugger_continue_small.png"));
con's avatar
con committed
469

470
471
    d->m_actions.stopAction = new QAction(tr("Interrupt"), this);
    d->m_actions.stopAction->setIcon(QIcon(":/debugger/images/debugger_interrupt_small.png"));
con's avatar
con committed
472

473
    d->m_actions.resetAction = new QAction(tr("Reset Debugger"), this);
con's avatar
con committed
474

475
476
    d->m_actions.nextAction = new QAction(tr("Step Over"), this);
    d->m_actions.nextAction->setIcon(QIcon(":/debugger/images/debugger_stepover_small.png"));
con's avatar
con committed
477

478
479
    d->m_actions.stepAction = new QAction(tr("Step Into"), this);
    d->m_actions.stepAction->setIcon(QIcon(":/debugger/images/debugger_stepinto_small.png"));
con's avatar
con committed
480

481
482
    d->m_actions.stepOutAction = new QAction(tr("Step Out"), this);
    d->m_actions.stepOutAction->setIcon(QIcon(":/debugger/images/debugger_stepout_small.png"));
con's avatar
con committed
483

484
    d->m_actions.runToLineAction = new QAction(tr("Run to Line"), this);
con's avatar
con committed
485

486
    d->m_actions.runToFunctionAction = new QAction(tr("Run to Outermost Function"), this);
con's avatar
con committed
487

488
    d->m_actions.jumpToLineAction = new QAction(tr("Jump to Line"), this);
con's avatar
con committed
489

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

492
    d->m_actions.watchAction = new QAction(tr("Add to Watch Window"), this);
con's avatar
con committed
493

494
495
496
    d->m_actions.reverseDirectionAction = new QAction(tr("Reverse Direction"), this);
    d->m_actions.reverseDirectionAction->setCheckable(true);
    d->m_actions.reverseDirectionAction->setChecked(false);
497

498
    connect(d->m_actions.continueAction, SIGNAL(triggered()),
con's avatar
con committed
499
        this, SLOT(continueExec()));
500
    connect(d->m_actions.stopAction, SIGNAL(triggered()),
con's avatar
con committed
501
        this, SLOT(interruptDebuggingRequest()));
502
    connect(d->m_actions.resetAction, SIGNAL(triggered()),
con's avatar
con committed
503
        this, SLOT(exitDebugger()));
504
    connect(d->m_actions.nextAction, SIGNAL(triggered()),
con's avatar
con committed
505
        this, SLOT(nextExec()));
506
    connect(d->m_actions.stepAction, SIGNAL(triggered()),
con's avatar
con committed
507
        this, SLOT(stepExec()));
508
    connect(d->m_actions.stepOutAction, SIGNAL(triggered()),
con's avatar
con committed
509
        this, SLOT(stepOutExec()));
510
    connect(d->m_actions.runToLineAction, SIGNAL(triggered()),
con's avatar
con committed
511
        this, SLOT(runToLineExec()));
512
    connect(d->m_actions.runToFunctionAction, SIGNAL(triggered()),
con's avatar
con committed
513
        this, SLOT(runToFunctionExec()));
514
    connect(d->m_actions.jumpToLineAction, SIGNAL(triggered()),
con's avatar
con committed
515
        this, SLOT(jumpToLineExec()));
516
    connect(d->m_actions.watchAction, SIGNAL(triggered()),
con's avatar
con committed
517
        this, SLOT(addToWatchWindow()));
518
    connect(d->m_actions.breakAction, SIGNAL(triggered()),
con's avatar
con committed
519
520
        this, SLOT(toggleBreakpoint()));

521
    connect(d->m_statusTimer, SIGNAL(timeout()),
522
        this, SLOT(clearStatusMessage()));
con's avatar
con committed
523

524
525
    connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
        this, SLOT(executeDebuggerCommand()));
526

527
528
    connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()),
        this, SLOT(watchPoint()));
con's avatar
con committed
529

530
531
    connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
        this, SLOT(operateByInstructionTriggered()));
532
533


534
    d->m_breakDock = d->m_mainWindow->addDockForWidget(d->m_breakWindow);
con's avatar
con committed
535

536
537
    d->m_modulesDock = d->m_mainWindow->addDockForWidget(d->m_modulesWindow);
    connect(d->m_modulesDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
538
539
        this, SLOT(reloadModules()), Qt::QueuedConnection);

540
541
    d->m_registerDock = d->m_mainWindow->addDockForWidget(d->m_registerWindow);
    connect(d->m_registerDock->toggleViewAction(), SIGNAL(toggled(bool)),
con's avatar
con committed
542
543
        this, SLOT(reloadRegisters()), Qt::QueuedConnection);

544
    d->m_outputDock = d->m_mainWindow->addDockForWidget(d->m_outputWindow);
con's avatar
con committed
545

546
    d->m_stackDock = d->m_mainWindow->addDockForWidget(d->m_stackWindow);
con's avatar
con committed
547

548
549
    d->m_sourceFilesDock = d->m_mainWindow->addDockForWidget(d->m_sourceFilesWindow);
    connect(d->m_sourceFilesDock->toggleViewAction(), SIGNAL(toggled(bool)),
550
551
        this, SLOT(reloadSourceFiles()), Qt::QueuedConnection);

552
    d->m_threadsDock = d->m_mainWindow->addDockForWidget(d->m_threadsWindow);
con's avatar
con committed
553

554
    QSplitter *localsAndWatchers = new QSplitter(Qt::Vertical, 0);
555
556
557
558
    localsAndWatchers->setWindowTitle(d->m_localsWindow->windowTitle());
    localsAndWatchers->addWidget(d->m_localsWindow);
    localsAndWatchers->addWidget(d->m_watchersWindow);
    //localsAndWatchers->addWidget(d->m_tooltipWindow);
559
560
    localsAndWatchers->setStretchFactor(0, 3);
    localsAndWatchers->setStretchFactor(1, 1);
561
    localsAndWatchers->setStretchFactor(2, 1);
562
    d->m_watchDock = d->m_mainWindow->addDockForWidget(localsAndWatchers);
563

hjk's avatar
hjk committed
564
    setState(DebuggerNotReady);
565
566
}

567
QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(unsigned enabledTypeFlags)
568
569
{
    QList<Core::IOptionsPage*> rc;
570

571
572
573
574
    if (enabledTypeFlags & GdbEngineType) {
        gdbEngine = createGdbEngine(this);
        gdbEngine->addOptionPages(&rc);
    }
575

576
    winEngine = createWinEngine(this, (enabledTypeFlags & CdbEngineType), &rc);
577
578
579
580
581
582
583
584
585
586
587

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

    if (enabledTypeFlags & TcfEngineType) {
        tcfEngine = createTcfEngine(this);
        tcfEngine->addOptionPages(&rc);
    }

588
    d->m_engine = 0;
589
    STATE_DEBUG(gdbEngine << winEngine << scriptEngine << rc.size());
590
    return rc;
con's avatar
con committed
591
592
}

593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
DebuggerManagerActions DebuggerManager::debuggerManagerActions() const
{
    return d->m_actions;
}

Core::Utils::FancyMainWindow *DebuggerManager::mainWindow() const
{
    return d->m_mainWindow;
}

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;
}

SourceFilesWindow *DebuggerManager::sourceFileWindow() const
{
    return d->m_sourceFilesWindow;
}

QWidget *DebuggerManager::threadsWindow() const
con's avatar
con committed
649
{
650
    return d->m_threadsWindow;
con's avatar
con committed
651
652
}

hjk's avatar
hjk committed
653
654
void DebuggerManager::createNewDock(QWidget *widget)
{
655
    QDockWidget *dockWidget = new QDockWidget(widget->windowTitle(), d->m_mainWindow);
hjk's avatar
hjk committed
656
657
658
    dockWidget->setObjectName(widget->windowTitle());
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
    dockWidget->setWidget(widget);
659
    d->m_mainWindow->addDockWidget(Qt::TopDockWidgetArea, dockWidget);
hjk's avatar
hjk committed
660
661
662
    dockWidget->show();
}

con's avatar
con committed
663
664
void DebuggerManager::setSimpleDockWidgetArrangement()
{
665
666
    d->m_mainWindow->setTrackingEnabled(false);
    QList<QDockWidget *> dockWidgets = d->m_mainWindow->dockWidgets();
667
668
    foreach (QDockWidget *dockWidget, dockWidgets) {
        dockWidget->setFloating(false);
669
        d->m_mainWindow->removeDockWidget(dockWidget);
670
    }
con's avatar
con committed
671

672
    foreach (QDockWidget *dockWidget, dockWidgets) {
673
        d->m_mainWindow->addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
con's avatar
con committed
674
675
676
        dockWidget->show();
    }

677
678
679
680
681
682
    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_outputDock);
    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);
con's avatar
con committed
683

684
685
    // They following views are rarely used in ordinary debugging. Hiding them
    // saves cycles since the corresponding information won't be retrieved.
686
687
688
689
690
    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
691
692
693
694
}

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

698
699
void DebuggerManager::clearStatusMessage()
{
700
    d->m_statusLabel->setText(d->m_lastPermanentStatusMessage);
701
702
}

con's avatar
con committed
703
704
705
void DebuggerManager::showStatusMessage(const QString &msg, int timeout)
{
    Q_UNUSED(timeout)
706
    showDebuggerOutput(LogStatus, msg);
707
    d->m_statusLabel->setText(QLatin1String("   ") + msg);
708
    if (timeout > 0) {
709
710
        d->m_statusTimer->setSingleShot(true);
        d->m_statusTimer->start(timeout);
711
    } else {
712
713
        d->m_lastPermanentStatusMessage = msg;
        d->m_statusTimer->stop();
714
    }
con's avatar
con committed
715
716
717
718
719
}

void DebuggerManager::notifyInferiorStopped()
{
    resetLocation();
hjk's avatar
hjk committed
720
    setState(InferiorStopped);
con's avatar
con committed
721
722
723
724
725
    showStatusMessage(tr("Stopped."), 5000);
}

void DebuggerManager::notifyInferiorRunning()
{
hjk's avatar
hjk committed
726
    setState(InferiorRunning);
con's avatar
con committed
727
728
729
730
731
    showStatusMessage(tr("Running..."), 5000);
}

void DebuggerManager::notifyInferiorExited()
{
hjk's avatar
hjk committed
732
    setState(DebuggerNotReady);
733
    showStatusMessage(tr("Exited."), 5000);
con's avatar
con committed
734
735
}

736
void DebuggerManager::notifyInferiorPidChanged(qint64 pid)
con's avatar
con committed
737
{
738
    STATE_DEBUG(d->m_inferiorPid << pid);
739

740
741
    if (d->m_inferiorPid != pid) {
        d->m_inferiorPid = pid;
742
743
        emit inferiorPidChanged(pid);
    }
con's avatar
con committed
744
745
}

Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
746
void DebuggerManager::showApplicationOutput(const QString &str)
con's avatar
con committed
747
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
748
     emit applicationOutputAvailable(str);
con's avatar
con committed
749
750
751
752
}

void DebuggerManager::shutdown()
{
753
754
755
756
    STATE_DEBUG(d->m_engine);
    if (d->m_engine)
        d->m_engine->shutdown();
    d->m_engine = 0;
757

758
759
760
761
762
    #define doDelete(ptr) delete ptr; ptr = 0
    doDelete(scriptEngine);
    doDelete(gdbEngine);
    doDelete(winEngine);
    doDelete(tcfEngine);
763

con's avatar
con committed
764
765
    // Delete these manually before deleting the manager
    // (who will delete the models for most views)
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
    doDelete(d->m_breakWindow);
    doDelete(d->m_modulesWindow);
    doDelete(d->m_outputWindow);
    doDelete(d->m_registerWindow);
    doDelete(d->m_stackWindow);
    doDelete(d->m_sourceFilesWindow);
    doDelete(d->m_threadsWindow);
    //doDelete(d->m_tooltipWindow);
    doDelete(d->m_watchersWindow);
    doDelete(d->m_localsWindow);

    doDelete(d->m_breakHandler);
    doDelete(d->m_threadsHandler);
    doDelete(d->m_modulesHandler);
    doDelete(d->m_registerHandler);
    doDelete(d->m_stackHandler);
    doDelete(d->m_watchHandler);
783
    #undef doDelete
con's avatar
con committed
784
785
}

786
787
BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lineNumber)
{
788
    if (!d->m_breakHandler)
789
        return 0;
790
791
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
    return index == -1 ? 0 : d->m_breakHandler->at(index);
792
793
}

con's avatar
con committed
794
795
796
797
798
799
800
801
802
803
804
805
void DebuggerManager::toggleBreakpoint()
{
    QString fileName;
    int lineNumber = -1;
    queryCurrentTextEditor(&fileName, &lineNumber, 0);
    if (lineNumber == -1)
        return;
    toggleBreakpoint(fileName, lineNumber);
}

void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
{
806
    STATE_DEBUG(fileName << lineNumber);
807
    QTC_ASSERT(d->m_breakHandler, return);
hjk's avatar
hjk committed
808
809
810
    if (state() != InferiorRunning
         && state() != InferiorStopped
         && state() != DebuggerNotReady) {
811
812
813
814
815
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

816
    int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
con's avatar
con committed
817
    if (index == -1)
818
        d->m_breakHandler->setBreakpoint(fileName, lineNumber);
con's avatar
con committed
819
    else
820
        d->m_breakHandler->removeBreakpoint(index);
821

hjk's avatar
hjk committed
822
    attemptBreakpointSynchronization();
con's avatar
con committed
823
824
}

825
826
void DebuggerManager::toggleBreakpointEnabled(const QString &fileName, int lineNumber)
{
827
    STATE_DEBUG(fileName << lineNumber);
828
    QTC_ASSERT(d->m_breakHandler, return);
hjk's avatar
hjk committed
829
830
831
    if (state() != InferiorRunning
         && state() != InferiorStopped
         && state() != DebuggerNotReady) {
832
833
834
835
836
        showStatusMessage(tr("Changing breakpoint state requires either a "
            "fully running or fully stopped application."));
        return;
    }

837
    d->m_breakHandler->toggleBreakpointEnabled(fileName, lineNumber);
hjk's avatar
hjk committed
838
839

    attemptBreakpointSynchronization();
840
841
}

842
843
void DebuggerManager::attemptBreakpointSynchronization()
{
844
845
    if (d->m_engine)
        d->m_engine->attemptBreakpointSynchronization();
846
847
}

848
void DebuggerManager::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
con's avatar
con committed
849
{
850
851
    if (d->m_engine)
        d->m_engine->setToolTipExpression(mousePos, editor, cursorPos);
con's avatar
con committed
852
853
}

854
void DebuggerManager::updateWatchData(const Debugger::Internal::WatchData &data)
855
{
856
857
    if (d->m_engine)
        d->m_engine->updateWatchData(data);
858
859
}

hjk's avatar
hjk committed
860
static QString msgEngineNotAvailable(const char *engine)
861
{
hjk's avatar
hjk committed
862
863
    return DebuggerManager::tr("The application requires the debugger engine '%1', "
        "which is disabled.").arg(QLatin1String(engine));
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
}

static IDebuggerEngine *debuggerEngineForToolChain(ProjectExplorer::ToolChain::ToolChainType tc)
{
    IDebuggerEngine *rc = 0;
    switch (tc) {
    case ProjectExplorer::ToolChain::LinuxICC:
    case ProjectExplorer::ToolChain::MinGW:
    case ProjectExplorer::ToolChain::GCC:
        rc = gdbEngine;
        break;
    case ProjectExplorer::ToolChain::MSVC:
    case ProjectExplorer::ToolChain::WINCE:
        rc = winEngine;
        break;
879
880
881
882
883
884
    case ProjectExplorer::ToolChain::WINSCW: // S60
    case ProjectExplorer::ToolChain::GCCE:
    case ProjectExplorer::ToolChain::RVCT_ARMV5:
    case ProjectExplorer::ToolChain::RVCT_ARMV6:
        rc = gdbEngine;
        break;
885
886
887
    case ProjectExplorer::ToolChain::OTHER:
    case ProjectExplorer::ToolChain::UNKNOWN:
    case ProjectExplorer::ToolChain::INVALID:
888
    default:
889
890
891
892
893
894
895
        break;
    }
    return rc;
}

// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
896
static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
897
898
899
                                                int toolChainType,
                                                QString *errorMessage,
                                                QString *settingsIdHint)
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
900
{
901
902
903
904
905
    if (executable.endsWith(_(".js"))) {
        if (!scriptEngine) {
            *errorMessage = msgEngineNotAvailable("Script Engine");
            return 0;
        }
906
        return scriptEngine;
907
    }
908

909
/*
hjk's avatar
hjk committed
910
    if (executable.endsWith(_(".sym"))) {
911
912
        if (!gdbEngine) {
            *errorMessage = msgEngineNotAvailable("Gdb Engine");
hjk's avatar
hjk committed
913
914
            return 0;
        }
915
        return gdbEngine;
hjk's avatar
hjk committed
916
    }
917
*/
hjk's avatar
hjk committed
918
919
920

    if (IDebuggerEngine *tce = debuggerEngineForToolChain(
            static_cast<ProjectExplorer::ToolChain::ToolChainType>(toolChainType)))
921
922
        return tce;

923
#ifndef Q_OS_WIN
924
    Q_UNUSED(settingsIdHint)
925
926
927
928
929
    if (!gdbEngine) {
        *errorMessage = msgEngineNotAvailable("Gdb Engine");
        return 0;
    }

930
    return gdbEngine;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
931
#else
932
933
934
    // A remote executable?
    if (!executable.endsWith(_(".exe")))
        return gdbEngine;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
935
936
937
    // If a file has PDB files, it has been compiled by VS.
    QStringList pdbFiles;
    if (!getPDBFiles(executable, &pdbFiles, errorMessage))
938
        return 0;
939
    if (pdbFiles.empty())
940
        return gdbEngine;
941

Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
942
943
944
    // We need the CDB debugger in order to be able to debug VS
    // executables
    if (!winEngine) {
945
946
        *errorMessage = DebuggerManager::tr("Debugging VS executables is currently not enabled.");
        *settingsIdHint = QLatin1String("Cdb");
947
        return 0;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
948
    }
949
    return winEngine;
Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
950
951
952
#endif
}

Friedemann Kleint's avatar
Friedemann Kleint committed
953
// Figure out the debugger type of a PID
954
static IDebuggerEngine *determineDebuggerEngine(int  /* pid */,
955
956
                                                int toolChainType,
                                                QString *errorMessage)
Friedemann Kleint's avatar
Friedemann Kleint committed
957
{
hjk's avatar
hjk committed
958
959
    if (IDebuggerEngine *tce = debuggerEngineForToolChain(
            static_cast<ProjectExplorer::ToolChain::ToolChainType>(toolChainType)))
960
        return tce;
Friedemann Kleint's avatar
Friedemann Kleint committed
961
962
#ifdef Q_OS_WIN
    // Preferably Windows debugger
963
964
965
966
967
968
    if (winEngine)
        return winEngine;
    if (gdbEngine)
        return gdbEngine;
    *errorMessage = msgEngineNotAvailable("Gdb Engine");
    return 0;
Friedemann Kleint's avatar
Friedemann Kleint committed
969
#else
970
971
972
973
974
    if (!gdbEngine) {
        *errorMessage = msgEngineNotAvailable("Gdb Engine");
        return 0;
    }

975
    return gdbEngine;
Friedemann Kleint's avatar
Friedemann Kleint committed
976
977
978
#endif
}

hjk's avatar
hjk committed
979
void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
con's avatar
con committed
980
{
981
982
983
984
    d->m_startParameters = sp;
    d->m_inferiorPid = d->m_startParameters->attachPID > 0
        ? d->m_startParameters->attachPID : 0;
    const QString toolChainName = ProjectExplorer::ToolChain::toolChainName(static_cast<ProjectExplorer::ToolChain::ToolChainType>(d->m_startParameters->toolChainType));
con's avatar
con committed
985
986

    emit debugModeRequested();
987
988
    showDebuggerOutput(LogStatus,
        tr("Starting debugger for tool chain '%1'...").arg(toolChainName));
989
    showDebuggerOutput(LogDebug, DebuggerSettings::instance()->dump());
con's avatar
con committed
990

Friedemann Kleint's avatar
m.txt    
Friedemann Kleint committed
991
    QString errorMessage;
992
    QString settingsIdHint;
993
    switch (d