debuggerengine.cpp 57.7 KB
Newer Older
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
8
9
10
11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12
13
14
15
16
17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21
22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23
24
25
26
27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
31
32
33
34
**
**************************************************************************/

#include "debuggerengine.h"

35
#include "debuggerinternalconstants.h"
36
#include "debuggeractions.h"
37
#include "debuggercore.h"
38
#include "debuggerplugin.h"
39
#include "debuggerrunner.h"
40
#include "debuggerstringutils.h"
Friedemann Kleint's avatar
Friedemann Kleint committed
41
#include "debuggerstartparameters.h"
42

43
44
#include "memoryagent.h"
#include "disassembleragent.h"
45
46
47
48
49
50
51
52
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"
53
#include "qtmessageloghandler.h"
54

hjk's avatar
hjk committed
55
#include <coreplugin/icore.h>
56
#include <coreplugin/idocument.h>
hjk's avatar
hjk committed
57
#include <coreplugin/editormanager/editormanager.h>
58
59
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
hjk's avatar
hjk committed
60
61

#include <texteditor/itexteditor.h>
62
#include <texteditor/basetextmark.h>
hjk's avatar
hjk committed
63

64
65
66
#include <projectexplorer/taskhub.h>
#include <extensionsystem/pluginmanager.h>

67
68
#include <utils/savedaction.h>
#include <utils/qtcassert.h>
69
#include <utils/fileinprojectfinder.h>
70

71
72
73
74
75
#include <QDebug>
#include <QTimer>
#include <QFile>
#include <QFileInfo>
#include <QFutureInterface>
76

77
#include <QMessageBox>
78

hjk's avatar
hjk committed
79
using namespace Core;
80
using namespace Debugger::Internal;
hjk's avatar
hjk committed
81
82
using namespace ProjectExplorer;
using namespace TextEditor;
83

84
85
86
87
enum { debug = 0 };

#define SDEBUG(s) if (!debug) {} else qDebug() << s;
#define XSDEBUG(s) qDebug() << s
88

89

90
91
92
93
94
95
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

96
97
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
98
99
100
101
102
103
104
105
106
Internal::Location::Location(const StackFrame &frame, bool marker)
{
    init();
    m_fileName = frame.file;
    m_lineNumber = frame.line;
    m_needsMarker = marker;
    m_functionName = frame.function;
    m_hasDebugInfo = frame.isUsable();
    m_address = frame.address;
107
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
108
109
}

110
111
QDebug operator<<(QDebug d, DebuggerState state)
{
hjk's avatar
hjk committed
112
113
    //return d << DebuggerEngine::stateName(state) << '(' << int(state) << ')';
    return d << DebuggerEngine::stateName(state);
114
115
116
117
118
119
120
}

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
121
            << " processArgs=" << sp.processArgs
122
123
124
125
126
127
128
            << " environment=<" << sp.environment.size() << " variables>"
            << " workingDir=" << sp.workingDirectory
            << " attachPID=" << sp.attachPID
            << " useTerminal=" << sp.useTerminal
            << " remoteChannel=" << sp.remoteChannel
            << " remoteArchitecture=" << sp.remoteArchitecture
            << " symbolFileName=" << sp.symbolFileName
hjk's avatar
hjk committed
129
            << " useServerStartScript=" << sp.useServerStartScript
130
            << " serverStartScript=" << sp.serverStartScript
131
            << " abi=" << sp.toolChainAbi.toString() << '\n';
132
133
134
    return str;
}

135

136
137
138
139
140
141
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

142
143
144
145
146
147
148
149
150
// transitions:
//   None->Requested
//   Requested->Succeeded
//   Requested->Failed
//   Requested->Cancelled
enum RemoteSetupState { RemoteSetupNone, RemoteSetupRequested,
                        RemoteSetupSucceeded, RemoteSetupFailed,
                        RemoteSetupCancelled };

151
class DebuggerEnginePrivate : public QObject
152
{
153
154
    Q_OBJECT

155
public:
156
157
    DebuggerEnginePrivate(DebuggerEngine *engine,
            DebuggerEngine *masterEngine,
158
            DebuggerLanguages languages,
159
            const DebuggerStartParameters &sp)
160
      : m_engine(engine),
161
        m_masterEngine(masterEngine),
162
163
        m_runControl(0),
        m_startParameters(sp),
164
        m_languages(languages),
165
        m_state(DebuggerNotReady),
hjk's avatar
hjk committed
166
        m_lastGoodState(DebuggerNotReady),
Friedemann Kleint's avatar
Friedemann Kleint committed
167
        m_targetState(DebuggerNotReady),
168
        m_remoteSetupState(RemoteSetupNone),
169
        m_inferiorPid(0),
170
        m_modulesHandler(),
171
        m_registerHandler(),
172
173
        m_sourceFilesHandler(),
        m_stackHandler(),
hjk's avatar
hjk committed
174
        m_threadsHandler(),
175
        m_watchHandler(engine),
176
        m_disassemblerAgent(engine),
177
        m_memoryAgent(engine),
178
        m_isStateDebugging(false),
179
        m_testsPossible(true),
180
        m_testsRunning(false),
181
        m_taskHub(0)
182
    {
183
        connect(&m_locationTimer, SIGNAL(timeout()), SLOT(resetLocation()));
184
        if (sp.toolChainAbi.os() == Abi::MacOS)
con's avatar
con committed
185
            m_disassemblerAgent.setTryMixed(false);
186
    }
187
188

    ~DebuggerEnginePrivate() {}
189

190
public slots:
191
    void doSetupEngine();
hjk's avatar
hjk committed
192
193
    void doSetupInferior();
    void doRunEngine();
hjk's avatar
hjk committed
194
195
    void doShutdownEngine();
    void doShutdownInferior();
196
    void doInterruptInferior();
hjk's avatar
hjk committed
197
    void doFinishDebugger();
hjk's avatar
hjk committed
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
    void queueSetupEngine()
    {
        m_engine->setState(EngineSetupRequested);
        m_engine->showMessage(_("QUEUE: SETUP ENGINE"));
        QTimer::singleShot(0, this, SLOT(doSetupEngine()));
    }

    void queueSetupInferior()
    {
        m_engine->setState(InferiorSetupRequested);
        m_engine->showMessage(_("QUEUE: SETUP INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doSetupInferior()));
    }

213
214
    void queueRunEngine()
    {
hjk's avatar
hjk committed
215
216
217
218
219
        m_engine->setState(EngineRunRequested);
        m_engine->showMessage(_("QUEUE: RUN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doRunEngine()));
    }

220
221
    void queueShutdownEngine()
    {
hjk's avatar
hjk committed
222
223
224
225
226
        m_engine->setState(EngineShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN ENGINE"));
        QTimer::singleShot(0, this, SLOT(doShutdownEngine()));
    }

227
228
    void queueShutdownInferior()
    {
hjk's avatar
hjk committed
229
230
231
232
233
        m_engine->setState(InferiorShutdownRequested);
        m_engine->showMessage(_("QUEUE: SHUTDOWN INFERIOR"));
        QTimer::singleShot(0, this, SLOT(doShutdownInferior()));
    }

234
235
    void queueFinishDebugger()
    {
236
237
238
        QTC_ASSERT(state() == EngineShutdownOk
            || state() == EngineShutdownFailed, qDebug() << state());
        m_engine->setState(DebuggerFinished);
239
240
241
242
243
        resetLocation();
        if (isMasterEngine()) {
            m_engine->showMessage(_("QUEUE: FINISH DEBUGGER"));
            QTimer::singleShot(0, this, SLOT(doFinishDebugger()));
        }
hjk's avatar
hjk committed
244
245
    }

246
247
    void raiseApplication()
    {
248
249
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
250
251
    }

252
    void scheduleResetLocation()
253
    {
254
        m_stackHandler.scheduleResetLocation();
255
        m_watchHandler.scheduleResetLocation();
256
        m_threadsHandler.scheduleResetLocation();
257
        m_disassemblerAgent.scheduleResetLocation();
258
259
260
261
        m_locationTimer.setSingleShot(true);
        m_locationTimer.start(80);
    }

262
    void resetLocation()
263
264
265
    {
        m_locationTimer.stop();
        m_locationMark.reset();
266
        m_stackHandler.resetLocation();
267
        m_watchHandler.resetLocation();
268
        m_threadsHandler.resetLocation();
269
        m_disassemblerAgent.resetLocation();
270
271
    }

272
public:
hjk's avatar
hjk committed
273
    DebuggerState state() const { return m_state; }
274
    RemoteSetupState remoteSetupState() const { return m_remoteSetupState; }
275
276
277
    bool isMasterEngine() const { return m_engine->isMasterEngine(); }
    DebuggerRunControl *runControl() const
        { return m_masterEngine ? m_masterEngine->runControl() : m_runControl; }
278
    void setRemoteSetupState(RemoteSetupState state);
hjk's avatar
hjk committed
279

280
    DebuggerEngine *m_engine; // Not owned.
281
    DebuggerEngine *m_masterEngine; // Not owned
282
283
284
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
285
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
286
287

    // The current state.
288
289
    DebuggerState m_state;

hjk's avatar
hjk committed
290
291
292
293
294
295
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

    // The state we are aiming for.
    DebuggerState m_targetState;

296
297
298
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

299
300
301
302
303
304
305
306
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
307
    QtMessageLogHandler m_qtMessageHandler;
308
    QFutureInterface<void> m_progress;
309

310
311
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
312
313
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
314
315

    bool m_isStateDebugging;
316

317
    Utils::FileInProjectFinder m_fileFinder;
318
319
320
    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
321
    void reportTestError(const QString &msg, int line);
322
    bool m_testsPossible;
323
    bool m_testsRunning;
David Schulz's avatar
David Schulz committed
324
325
    bool m_breakOnError;
    bool m_foundError;
326
    QStringList m_testContents;
327
328
    TaskHub *m_taskHub;
    QString m_testFileName;
329
330
331
332
333
334
335
336
337
};


//////////////////////////////////////////////////////////////////////
//
// DebuggerEngine
//
//////////////////////////////////////////////////////////////////////

338
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
339
        DebuggerLanguages languages,
340
        DebuggerEngine *parentEngine)
341
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
342
{
343
    d->m_inferiorPid = 0;
344
345
346
347
}

DebuggerEngine::~DebuggerEngine()
{
348
349
    disconnect();
    delete d;
350
351
}

352
353
354
355
356
357
358
359
360
361
362
const char *DebuggerEngine::stateName(int s)
{
#    define SN(x) case x: return #x;
    switch (s) {
        SN(DebuggerNotReady)
        SN(EngineSetupRequested)
        SN(EngineSetupOk)
        SN(EngineSetupFailed)
        SN(EngineRunFailed)
        SN(InferiorSetupRequested)
        SN(InferiorSetupFailed)
363
        SN(InferiorSetupOk)
364
365
366
367
368
369
370
371
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
372
        SN(InferiorExitOk)
373
374
375
376
377
378
379
380
381
382
383
384
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

385
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
386
{
387
    showMessage(msg, StatusBar, timeout);
388
}
389

390
391
392
393
394
395
396
397
398
399
400
401
void DebuggerEngine::frameUp()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMin(currentIndex + 1, stackHandler()->stackSize() - 1));
}

void DebuggerEngine::frameDown()
{
    int currentIndex = stackHandler()->currentIndex();
    activateFrame(qMax(currentIndex - 1, 0));
}

402
403
404
405
406
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

407
408
ModulesHandler *DebuggerEngine::modulesHandler() const
{
409
410
411
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
412
413
414
415
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
416
417
418
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
419
420
421
422
}

StackHandler *DebuggerEngine::stackHandler() const
{
Aurindam Jana's avatar
Aurindam Jana committed
423
424
425
    return d->m_masterEngine
        ? d->m_masterEngine->stackHandler()
        : &d->m_stackHandler;
426
427
428
429
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
430
431
432
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
433
434
435
436
}

WatchHandler *DebuggerEngine::watchHandler() const
{
437
438
439
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
440
441
}

442
443
444
445
446
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
    return &d->m_qtMessageHandler;
}

447
448
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
449
450
451
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
452
453
454
455
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
456
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
457
458
459
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
460
461
462
463
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
464
    QAbstractItemModel *model = registerHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
465
466
467
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
468
469
470
471
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
472
    QAbstractItemModel *model = stackHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
473
474
475
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
476
477
478
479
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
480
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
481
482
483
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
484
485
486
487
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
488
    QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
489
490
491
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
492
493
494
495
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
496
    QAbstractItemModel *model = watchHandler()->model(WatchersWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
497
498
499
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
500
501
502
503
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
504
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
505
506
507
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
508
509
}

510
511
512
513
514
515
516
517
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

518
519
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
520
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
521
522
523
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
524
525
}

526
527
528
529
530
531
532
533
QAbstractItemModel *DebuggerEngine::qtMessageLogModel() const
{
    QAbstractItemModel *model = qtMessageLogHandler()->model();
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("QtMessageLogModel"));
    return model;
}

534
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
535
536
537
538
539
540
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
541
542
543
544
545
546
547
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

548
549
550
551
552
553
554
555
void DebuggerEngine::setRegisterValue(int regnr, const QString &value)
{
    Q_UNUSED(regnr);
    Q_UNUSED(value);
}

void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) const
{
556
557
558
559
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
560
561
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
562
563
564
    if (channel == QtMessageLogOutput)
        qtMessageLogHandler()->appendMessage(QtMessageLogHandler::UndefinedType, msg);

565
    debuggerCore()->showMessage(msg, channel, timeout);
566
567
568
569
570
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
571
572
573
574
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
575
576
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
577

578
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
579
    Core::FutureProgress *fp = Core::ICore::progressManager()
580
581
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
582
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
583
584
    d->m_progress.reportStarted();

585
586
587
588
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
589
590
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
591

592
593
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
594

hjk's avatar
hjk committed
595
    debuggerCore()->action(OperateByInstruction)
596
        ->setEnabled(hasCapability(DisassemblerCapability));
597

598
599
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
600
601
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
602
    d->m_progress.setProgressValue(200);
603
    d->queueSetupEngine();
604
605
606
607
}

void DebuggerEngine::resetLocation()
{
608
609
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
610
611
}

612
void DebuggerEngine::gotoLocation(const Location &loc)
613
{
Aurindam Jana's avatar
Aurindam Jana committed
614
615
     d->resetLocation();

616
617
618
619
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
620
621
622
623
624
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


625
626
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
627
628
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
629
    IEditor *editor = 0;
hjk's avatar
hjk committed
630
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
631
        editor = editorManager->openEditor(file, Core::Id(),
632
633
634
635
636
637
638
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
639
    }
640
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
641
642
643
    if (texteditor)
        texteditor->gotoLine(line, 0);

644
    if (loc.needsMarker()) {
Daniel Teske's avatar
Daniel Teske committed
645
        d->m_locationMark.reset(new TextEditor::BaseTextMark(file, line));
646
647
648
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
    }
649
650

    // FIXME: Breaks with split views.
651
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
652
        editorManager->activateEditor(editor);
653
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
654
655
}

656
657
658
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
659
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
660
    d->m_runControl = 0;
661
    d->m_progress.setProgressValue(900);
662
663
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
664
665
}

666
667
// Called from RunControl.
void DebuggerEngine::handleFinished()
668
{
669
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
670
    d->m_runControl = 0;
671
672
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
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
    modulesHandler()->removeAll();
    stackHandler()->removeAll();
    threadsHandler()->removeAll();
    watchHandler()->cleanup();
}

const DebuggerStartParameters &DebuggerEngine::startParameters() const
{
    return d->m_startParameters;
}

DebuggerStartParameters &DebuggerEngine::startParameters()
{
    return d->m_startParameters;
}


//////////////////////////////////////////////////////////////////////
//
// Dumpers. "Custom dumpers" are a library compiled against the current
// Qt containing functions to evaluate values of Qt classes
// (such as QString, taking pointers to their addresses).
// The library must be loaded into the debuggee.
//
//////////////////////////////////////////////////////////////////////

bool DebuggerEngine::qtDumperLibraryEnabled() const
{
hjk's avatar
hjk committed
701
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
702
703
704
705
706
707
708
709
710
}

QStringList DebuggerEngine::qtDumperLibraryLocations() const
{
    return d->m_startParameters.dumperLibraryLocations;
}

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
711
    debuggerCore()->showQtDumperLibraryWarning(details);
712
713
714
715
716
717
718
719
720
721
722
723
}

QString DebuggerEngine::qtDumperLibraryName() const
{
    return startParameters().dumperLibrary;
}

DebuggerState DebuggerEngine::state() const
{
    return d->m_state;
}

hjk's avatar
hjk committed
724
DebuggerState DebuggerEngine::lastGoodState() const
725
{
hjk's avatar
hjk committed
726
727
728
729
730
731
732
    return d->m_lastGoodState;
}

DebuggerState DebuggerEngine::targetState() const
{
    return d->m_targetState;
}
733

hjk's avatar
hjk committed
734
735
736
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
737
    case DebuggerNotReady:
738
        return to == EngineSetupRequested;
739

hjk's avatar
hjk committed
740
    case EngineSetupRequested:
741
742
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
743
744
745
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
746
    case EngineSetupOk:
hjk's avatar
hjk committed
747
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
748

hjk's avatar
hjk committed
749
    case InferiorSetupRequested:
750
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
751
    case InferiorSetupFailed:
hjk's avatar
hjk committed
752
        return to == EngineShutdownRequested;
753
754
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
755
756

    case EngineRunRequested:
hjk's avatar
hjk committed
757
758
759
760
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
761
    case EngineRunFailed:
762
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
763
764
765
766
767
768

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
769
770
771
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
772
773
774
775
776

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
777
            || to == InferiorStopOk || InferiorExitOk;
778
    case InferiorStopFailed:
hjk's avatar
hjk committed
779
        return to == EngineShutdownRequested;
780

781
782
783
    case InferiorExitOk:
        return to == InferiorShutdownOk;

784
    case InferiorUnrunnable:
hjk's avatar
hjk committed
785
786
787
788
789
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
790
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
791
        return to == EngineShutdownRequested;
792

hjk's avatar
hjk committed
793
    case EngineShutdownRequested:
794
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
795
796
797
798
799
800
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
801
        return to == EngineSetupRequested; // Happens on restart.
802
803
    }

804
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
805
806
807
    return false;
}

808
809
void DebuggerEngine::setupSlaveEngine()
{
810
    QTC_CHECK(state() == DebuggerNotReady);
811
812
813
814
815
816
817
818
819
820
    d->queueSetupEngine();
}

void DebuggerEnginePrivate::doSetupEngine()
{
    m_engine->showMessage(_("CALL: SETUP ENGINE"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << m_engine << state());
    m_engine->setupEngine();
}

821
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
822
{
hjk's avatar
hjk committed
823
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
824
825
826
827
828
829
830
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

831
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
832
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
833
    if (isMasterEngine() && runControl())
834
        runControl()->startFailed();
hjk's avatar
hjk committed
835
    setState(DebuggerFinished);
hjk's avatar
hjk committed
836
837
}

838
void DebuggerEngine::notifyEngineSetupOk()
839
{
hjk's avatar
hjk committed
840
    showMessage(_("NOTE: ENGINE SETUP OK"));
841
842
843
844
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

845
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
846
    setState(EngineSetupOk);
hjk's avatar
hjk committed
847
    showMessage(_("QUEUE: SETUP INFERIOR"));
848
    if (isMasterEngine())
849
850
851
852
853
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
854
    QTC_CHECK(state() == EngineSetupOk);
855
    d->queueSetupInferior();
856
857
}

hjk's avatar
hjk committed
858
void DebuggerEnginePrivate::doSetupInferior()
859
{
860
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
861
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
862
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
863
864
865
866
867
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
868
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
869
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
870
    showStatusMessage(tr("Setup failed."));
hjk's avatar
hjk committed
871
    setState(InferiorSetupFailed);
872
873
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
874
875
876
877
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
878
    showMessage(_("NOTE: INFERIOR SETUP OK"));
879
880
881
882
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
883
884
}

885
886
887
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
888
    QTC_CHECK(state() == InferiorSetupOk);
889
890
891
    d->queueRunEngine();
}

hjk's avatar
hjk committed
892
893
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
894
    m_engine->showMessage(_("CALL: RUN ENGINE"));
895
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
896
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
897
898
899
    m_engine->runEngine();
}

hjk's avatar
hjk committed
900
901
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
902
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
903
904
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
905
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
906
    showStatusMessage(tr("Loading finished."));
hjk's avatar
hjk committed
907
908
909
910
911
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
912
    showMessage(_("NOTE: ENGINE RUN FAILED"));
913
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
914
915
916
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
917
    showStatusMessage(tr("Run failed."));
hjk's avatar
hjk committed
918
    setState(EngineRunFailed);
919
920
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
921
922
}

923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
void DebuggerEngine::notifyEngineRequestRemoteSetup()
{
    showMessage(_("NOTE: REQUEST REMOTE SETUP"));
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone, qDebug() << this
               << "remoteSetupState" << d->remoteSetupState());

    d->setRemoteSetupState(RemoteSetupRequested);
    emit requestRemoteSetup();
}

void DebuggerEngine::notifyEngineRemoteSetupDone()
{
    showMessage(_("NOTE: REMOTE SETUP DONE"));
    QTC_ASSERT(state() == EngineSetupRequested
               || state() == EngineSetupFailed
               || state() == DebuggerFinished, qDebug() << this << state());

    QTC_ASSERT(d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupCancelled,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

    if (d->remoteSetupState() == RemoteSetupCancelled)
        return;

    d->setRemoteSetupState(RemoteSetupSucceeded);
}

void DebuggerEngine::notifyEngineRemoteSetupFailed()
{
    showMessage(_("NOTE: REMOTE SETUP FAILED"));
    QTC_ASSERT(state() == EngineSetupRequested
               || state() == EngineSetupFailed
               || state() == DebuggerFinished, qDebug() << this << state());

    QTC_ASSERT(d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupCancelled,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
}

hjk's avatar
hjk committed
963
964
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
965
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
966
967
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
968
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
969
    showStatusMessage(tr("Running."));
hjk's avatar
hjk committed
970
    setState(InferiorRunOk);
hjk's avatar
hjk committed
971
972
973
974
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
975
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
976
977
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
978
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
979
    showStatusMessage(tr("Stopped."));
hjk's avatar
hjk committed
980
    setState(InferiorStopOk);
hjk's avatar
hjk committed
981
982
983
984
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
985
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
986
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
987
    showStatusMessage(tr("Run requested..."));
hjk's avatar
hjk committed
988
989
990
991
992
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
993
    showMessage(_("NOTE: INFERIOR RUN OK"));
994
    showStatusMessage(tr("Running."));
995
996
997
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
998
999
1000
1001
1002
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
1003
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
1004
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
1005
1006
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
1007
1008
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
1009
1010
1011
1012
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
1013
1014
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
1015
    if (isDying()) {
hjk's avatar
hjk committed
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
        showMessage(_("NOTE: ... WHILE DYING. "));
        // Forward state to "StopOk" if needed.
        if (state() == InferiorStopRequested
                || state() == InferiorRunRequested
                || state() == InferiorRunOk) {
            showMessage(_("NOTE: ... FORWARDING TO 'STOP OK'. "));
            setState(InferiorStopOk);
        }
        if (state() == InferiorStopOk || state() == InferiorStopFailed) {
            d->queueShutdownInferior();
        }
        showMessage(_("NOTE: ... IGNORING STOP MESSAGE"));
        return;
hjk's avatar
hjk committed
1029
    }
1030
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
1031
    showStatusMessage(tr("Stopped."));
hjk's avatar
hjk committed
1032
    setState(InferiorStopOk);
hjk's avatar
hjk committed
1033
1034
}

hjk's avatar
hjk committed
1035