debuggerengine.cpp 55.1 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
53
#include "breakhandler.h"
#include "moduleshandler.h"
#include "registerhandler.h"
#include "snapshothandler.h"
#include "sourcefileshandler.h"
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"

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

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

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

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

#include <QtCore/QDebug>
#include <QtCore/QTimer>
71
#include <QtCore/QFile>
72
#include <QtCore/QFileInfo>
73
#include <QtCore/QFutureInterface>
74

75
#include <QtGui/QMessageBox>
76

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

82
83
84
85
enum { debug = 0 };

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

87

88
89
90
91
92
93
///////////////////////////////////////////////////////////////////////
//
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////

94
95
namespace Debugger {

Friedemann Kleint's avatar
Friedemann Kleint committed
96
97
98
99
100
101
102
103
104
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;
105
    m_from = frame.from;
Friedemann Kleint's avatar
Friedemann Kleint committed
106
107
}

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

QDebug operator<<(QDebug str, const DebuggerStartParameters &sp)
{
    QDebug nospace = str.nospace();
    nospace << "executable=" << sp.executable
            << " coreFile=" << sp.coreFile
119
            << " processArgs=" << sp.processArgs
120
121
122
123
124
125
126
            << " 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
127
            << " useServerStartScript=" << sp.useServerStartScript
128
            << " serverStartScript=" << sp.serverStartScript
129
            << " abi=" << sp.toolChainAbi.toString() << '\n';
130
131
132
    return str;
}

133

134
135
136
137
138
139
//////////////////////////////////////////////////////////////////////
//
// DebuggerEnginePrivate
//
//////////////////////////////////////////////////////////////////////

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

149
class DebuggerEnginePrivate : public QObject
150
{
151
152
    Q_OBJECT

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

    ~DebuggerEnginePrivate() {}
186

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

196
197
198
199
200
201
202
203
204
205
206
207
208
209
    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()));
    }

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

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

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

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

243
244
    void raiseApplication()
    {
245
246
        QTC_ASSERT(runControl(), return);
        runControl()->bringApplicationToForeground(m_inferiorPid);
247
248
    }

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

259
    void resetLocation()
260
261
262
    {
        m_locationTimer.stop();
        m_locationMark.reset();
263
        m_stackHandler.resetLocation();
264
        m_watchHandler.resetLocation();
265
        m_threadsHandler.resetLocation();
266
        m_disassemblerAgent.resetLocation();
267
268
    }

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

277
    DebuggerEngine *m_engine; // Not owned.
278
    DebuggerEngine *m_masterEngine; // Not owned
279
280
281
    DebuggerRunControl *m_runControl;  // Not owned.

    DebuggerStartParameters m_startParameters;
282
    DebuggerLanguages m_languages;
hjk's avatar
hjk committed
283
284

    // The current state.
285
286
    DebuggerState m_state;

hjk's avatar
hjk committed
287
288
289
290
291
292
    // The state we had before something unexpected happend.
    DebuggerState m_lastGoodState;

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

293
294
295
    // State of RemoteSetup signal/slots.
    RemoteSetupState m_remoteSetupState;

296
297
298
299
300
301
302
303
    qint64 m_inferiorPid;

    ModulesHandler m_modulesHandler;
    RegisterHandler m_registerHandler;
    SourceFilesHandler m_sourceFilesHandler;
    StackHandler m_stackHandler;
    ThreadsHandler m_threadsHandler;
    WatchHandler m_watchHandler;
304
    QFutureInterface<void> m_progress;
305

306
307
    DisassemblerAgent m_disassemblerAgent;
    MemoryAgent m_memoryAgent;
308
309
    QScopedPointer<TextEditor::BaseTextMark> m_locationMark;
    QTimer m_locationTimer;
310
311

    bool m_isStateDebugging;
312
313
314
315

    // Testing
    void handleAutoTests();
    void handleAutoTestLine(int line);
316
    void reportTestError(const QString &msg, int line);
317
318
    bool m_testsPossible;
    QStringList m_testContents;
319
320
    TaskHub *m_taskHub;
    QString m_testFileName;
321
322
323
324
325
326
327
328
329
};


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

330
DebuggerEngine::DebuggerEngine(const DebuggerStartParameters &startParameters,
331
        DebuggerLanguages languages,
332
        DebuggerEngine *parentEngine)
333
  : d(new DebuggerEnginePrivate(this, parentEngine, languages, startParameters))
334
{
335
    d->m_inferiorPid = 0;
336
337
338
339
}

DebuggerEngine::~DebuggerEngine()
{
340
341
    disconnect();
    delete d;
342
343
}

344
345
346
347
348
349
350
351
352
353
354
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)
355
        SN(InferiorSetupOk)
356
357
358
359
360
361
362
363
        SN(EngineRunRequested)
        SN(InferiorRunRequested)
        SN(InferiorRunOk)
        SN(InferiorRunFailed)
        SN(InferiorUnrunnable)
        SN(InferiorStopRequested)
        SN(InferiorStopOk)
        SN(InferiorStopFailed)
364
        SN(InferiorExitOk)
365
366
367
368
369
370
371
372
373
374
375
376
        SN(InferiorShutdownRequested)
        SN(InferiorShutdownOk)
        SN(InferiorShutdownFailed)
        SN(EngineShutdownRequested)
        SN(EngineShutdownOk)
        SN(EngineShutdownFailed)
        SN(DebuggerFinished)
    }
    return "<unknown>";
#    undef SN
}

377
void DebuggerEngine::showStatusMessage(const QString &msg, int timeout) const
378
{
379
    showMessage(msg, StatusBar, timeout);
380
}
381

382
383
384
385
386
387
388
389
390
391
392
393
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));
}

394
395
396
397
398
void DebuggerEngine::setTargetState(DebuggerState state)
{
    d->m_targetState = state;
}

399
400
ModulesHandler *DebuggerEngine::modulesHandler() const
{
401
402
403
    return d->m_masterEngine
        ? d->m_masterEngine->modulesHandler()
        : &d->m_modulesHandler;
404
405
406
407
}

RegisterHandler *DebuggerEngine::registerHandler() const
{
408
409
410
    return d->m_masterEngine
        ? d->m_masterEngine->registerHandler()
        : &d->m_registerHandler;
411
412
413
414
}

StackHandler *DebuggerEngine::stackHandler() const
{
hjk's avatar
hjk committed
415
416
417
418
    //return d->m_masterEngine
    //    ? d->m_masterEngine->stackHandler()
    //    : &d->m_stackHandler;
    return &d->m_stackHandler;
419
420
421
422
}

ThreadsHandler *DebuggerEngine::threadsHandler() const
{
423
424
425
    return d->m_masterEngine
        ? d->m_masterEngine->threadsHandler()
        : &d->m_threadsHandler;
426
427
428
429
}

WatchHandler *DebuggerEngine::watchHandler() const
{
430
431
432
    return d->m_masterEngine
        ? d->m_masterEngine->watchHandler()
        : &d->m_watchHandler;
433
434
435
436
}

SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
437
438
439
    return d->m_masterEngine
        ? d->m_masterEngine->sourceFilesHandler()
        : &d->m_sourceFilesHandler;
440
441
442
443
}

QAbstractItemModel *DebuggerEngine::modulesModel() const
{
444
    QAbstractItemModel *model = modulesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
445
446
447
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ModulesModel"));
    return model;
448
449
450
451
}

QAbstractItemModel *DebuggerEngine::registerModel() const
{
452
    QAbstractItemModel *model = registerHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
453
454
455
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("RegisterModel"));
    return model;
456
457
458
459
}

QAbstractItemModel *DebuggerEngine::stackModel() const
{
460
    QAbstractItemModel *model = stackHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
461
462
463
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("StackModel"));
    return model;
464
465
466
467
}

QAbstractItemModel *DebuggerEngine::threadsModel() const
{
468
    QAbstractItemModel *model = threadsHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
469
470
471
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ThreadsModel"));
    return model;
472
473
474
475
}

QAbstractItemModel *DebuggerEngine::localsModel() const
{
476
    QAbstractItemModel *model = watchHandler()->model(LocalsWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
477
478
479
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("LocalsModel"));
    return model;
480
481
482
483
}

QAbstractItemModel *DebuggerEngine::watchersModel() const
{
484
    QAbstractItemModel *model = watchHandler()->model(WatchersWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
485
486
487
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("WatchersModel"));
    return model;
488
489
490
491
}

QAbstractItemModel *DebuggerEngine::returnModel() const
{
492
    QAbstractItemModel *model = watchHandler()->model(ReturnWatch);
Friedemann Kleint's avatar
Friedemann Kleint committed
493
494
495
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("ReturnModel"));
    return model;
496
497
}

498
499
500
501
502
503
504
505
QAbstractItemModel *DebuggerEngine::toolTipsModel() const
{
    QAbstractItemModel *model = watchHandler()->model(TooltipsWatch);
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("TooltipsModel"));
    return model;
}

506
507
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
508
    QAbstractItemModel *model = sourceFilesHandler()->model();
Friedemann Kleint's avatar
Friedemann Kleint committed
509
510
511
    if (model->objectName().isEmpty()) // Make debugging easier.
        model->setObjectName(objectName() + QLatin1String("SourceFilesModel"));
    return model;
512
513
}

514
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
515
516
517
518
519
520
        quint64 addr, quint64 length)
{
    Q_UNUSED(addr);
    Q_UNUSED(length);
}

hjk's avatar
hjk committed
521
522
523
524
525
526
527
void DebuggerEngine::changeMemory(MemoryAgent *, QObject *,
        quint64 addr, const QByteArray &data)
{
    Q_UNUSED(addr);
    Q_UNUSED(data);
}

528
529
530
531
532
533
534
535
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
{
536
537
538
539
    if (d->m_masterEngine) {
        d->m_masterEngine->showMessage(msg, channel, timeout);
        return;
    }
540
541
    //if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
    //    qDebug() << qPrintable(msg) << "IN STATE" << state();
542
    debuggerCore()->showMessage(msg, channel, timeout);
543
544
545
546
547
    if (d->m_runControl) {
        d->m_runControl->showMessage(msg, channel);
    } else {
        qWarning("Warning: %s (no active run control)", qPrintable(msg));
    }
548
549
550
551
}

void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
{
552
553
    QTC_ASSERT(runControl, notifyEngineSetupFailed(); return);
    QTC_ASSERT(!d->m_runControl, notifyEngineSetupFailed(); return);
554

555
    d->m_progress.setProgressRange(0, 1000);
hjk's avatar
hjk committed
556
    Core::FutureProgress *fp = Core::ICore::progressManager()
557
558
        ->addTask(d->m_progress.future(),
        tr("Launching"), _("Debugger.Launcher"));
con's avatar
con committed
559
    fp->setKeepOnFinish(Core::FutureProgress::HideOnFinish);
560
561
    d->m_progress.reportStarted();

562
563
564
565
    d->m_runControl = runControl;

    d->m_inferiorPid = d->m_startParameters.attachPID > 0
        ? d->m_startParameters.attachPID : 0;
566
567
    if (d->m_inferiorPid)
        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
568

569
570
    if (!d->m_startParameters.environment.size())
        d->m_startParameters.environment = Utils::Environment();
571

hjk's avatar
hjk committed
572
    debuggerCore()->action(OperateByInstruction)
573
        ->setEnabled(hasCapability(DisassemblerCapability));
574

575
576
    QTC_ASSERT(state() == DebuggerNotReady || state() == DebuggerFinished,
         qDebug() << state());
577
578
    d->m_lastGoodState = DebuggerNotReady;
    d->m_targetState = DebuggerNotReady;
579
    d->m_progress.setProgressValue(200);
580
    d->queueSetupEngine();
581
582
583
584
}

void DebuggerEngine::resetLocation()
{
585
586
    // Do it after some delay to avoid flicker.
    d->scheduleResetLocation();
587
588
}

589
void DebuggerEngine::gotoLocation(const Location &loc)
590
{
Aurindam Jana's avatar
Aurindam Jana committed
591
592
     d->resetLocation();

593
594
595
596
    if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
        d->m_disassemblerAgent.setLocation(loc);
        return;
    }
597
598
599
600
601
    // CDB might hit on breakpoints while shutting down.
    //if (m_shuttingDown)
    //    return;


602
603
    const QString file = loc.fileName();
    const int line = loc.lineNumber();
hjk's avatar
hjk committed
604
605
    EditorManager *editorManager = EditorManager::instance();
    QList<IEditor *> editors = editorManager->editorsForFileName(file);
606
    IEditor *editor = 0;
hjk's avatar
hjk committed
607
    if (editors.isEmpty()) {
hjk's avatar
hjk committed
608
        editor = editorManager->openEditor(file, Core::Id(),
609
610
611
612
613
614
615
            EditorManager::IgnoreNavigationHistory);
        if (editor) {
            editors.append(editor);
            editor->setProperty(Constants::OPENED_BY_DEBUGGER, true);
        }
    } else {
        editor = editors.back();
hjk's avatar
hjk committed
616
    }
617
    ITextEditor *texteditor = qobject_cast<ITextEditor *>(editor);
hjk's avatar
hjk committed
618
619
620
    if (texteditor)
        texteditor->gotoLine(line, 0);

621
622
623
624
625
626
    if (loc.needsMarker()) {
        d->m_locationMark.reset(new TextEditor::BaseTextMark);
        d->m_locationMark->setLocation(file, line);
        d->m_locationMark->setIcon(debuggerCore()->locationMarkIcon());
        d->m_locationMark->setPriority(TextEditor::ITextMark::HighPriority);
    }
627
628

    // FIXME: Breaks with split views.
629
    if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
630
        editorManager->activateEditor(editor);
631
    //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
632
633
}

634
635
636
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
637
    showMessage(QLatin1String("HANDLE RUNCONTROL START FAILED"));
638
    d->m_runControl = 0;
639
    d->m_progress.setProgressValue(900);
640
641
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
642
643
}

644
645
// Called from RunControl.
void DebuggerEngine::handleFinished()
646
{
647
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
648
    d->m_runControl = 0;
649
650
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
    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
679
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
680
681
682
683
684
685
686
687
688
}

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

void DebuggerEngine::showQtDumperLibraryWarning(const QString &details)
{
689
    debuggerCore()->showQtDumperLibraryWarning(details);
690
691
692
693
694
695
696
697
698
699
700
701
}

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

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

hjk's avatar
hjk committed
702
DebuggerState DebuggerEngine::lastGoodState() const
703
{
hjk's avatar
hjk committed
704
705
706
707
708
709
710
    return d->m_lastGoodState;
}

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

hjk's avatar
hjk committed
712
713
714
static bool isAllowedTransition(DebuggerState from, DebuggerState to)
{
    switch (from) {
715
    case DebuggerNotReady:
716
        return to == EngineSetupRequested;
717

hjk's avatar
hjk committed
718
    case EngineSetupRequested:
719
720
        return to == EngineSetupOk || to == EngineSetupFailed;
    case EngineSetupFailed:
721
722
723
        // In is the engine's task to go into a proper "Shutdown"
        // state before calling notifyEngineSetupFailed
        return to == DebuggerFinished;
724
    case EngineSetupOk:
hjk's avatar
hjk committed
725
        return to == InferiorSetupRequested || to == EngineShutdownRequested;
726

hjk's avatar
hjk committed
727
    case InferiorSetupRequested:
728
        return to == InferiorSetupOk || to == InferiorSetupFailed;
hjk's avatar
hjk committed
729
    case InferiorSetupFailed:
hjk's avatar
hjk committed
730
        return to == EngineShutdownRequested;
731
732
    case InferiorSetupOk:
        return to == EngineRunRequested;
hjk's avatar
hjk committed
733
734

    case EngineRunRequested:
hjk's avatar
hjk committed
735
736
737
738
        return to == EngineRunFailed
            || to == InferiorRunOk
            || to == InferiorStopOk
            || to == InferiorUnrunnable;
hjk's avatar
hjk committed
739
    case EngineRunFailed:
740
        return to == EngineShutdownRequested;
hjk's avatar
hjk committed
741
742
743
744
745
746

    case InferiorRunRequested:
        return to == InferiorRunOk || to == InferiorRunFailed;
    case InferiorRunFailed:
        return to == InferiorStopOk;
    case InferiorRunOk:
747
748
749
        return to == InferiorStopRequested
            || to == InferiorStopOk // A spontaneous stop.
            || to == InferiorExitOk;
hjk's avatar
hjk committed
750
751
752
753
754

    case InferiorStopRequested:
        return to == InferiorStopOk || to == InferiorStopFailed;
    case InferiorStopOk:
        return to == InferiorRunRequested || to == InferiorShutdownRequested
755
            || to == InferiorStopOk || InferiorExitOk;
756
    case InferiorStopFailed:
hjk's avatar
hjk committed
757
        return to == EngineShutdownRequested;
758

759
760
761
    case InferiorExitOk:
        return to == InferiorShutdownOk;

762
    case InferiorUnrunnable:
hjk's avatar
hjk committed
763
764
765
766
767
        return to == InferiorShutdownRequested;
    case InferiorShutdownRequested:
        return to == InferiorShutdownOk || to == InferiorShutdownFailed;
    case InferiorShutdownOk:
        return to == EngineShutdownRequested;
768
    case InferiorShutdownFailed:
hjk's avatar
hjk committed
769
        return to == EngineShutdownRequested;
770

hjk's avatar
hjk committed
771
    case EngineShutdownRequested:
772
        return to == EngineShutdownOk || to == EngineShutdownFailed;
hjk's avatar
hjk committed
773
774
775
776
777
778
    case EngineShutdownOk:
        return to == DebuggerFinished;
    case EngineShutdownFailed:
        return to == DebuggerFinished;

    case DebuggerFinished:
779
        return to == EngineSetupRequested; // Happens on restart.
780
781
    }

782
    qDebug() << "UNKNOWN DEBUGGER STATE:" << from;
783
784
785
    return false;
}

786
787
void DebuggerEngine::setupSlaveEngine()
{
788
    QTC_CHECK(state() == DebuggerNotReady);
789
790
791
792
793
794
795
796
797
798
    d->queueSetupEngine();
}

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

799
void DebuggerEngine::notifyEngineSetupFailed()
hjk's avatar
hjk committed
800
{
hjk's avatar
hjk committed
801
    showMessage(_("NOTE: ENGINE SETUP FAILED"));
802
803
804
805
806
807
808
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupRequested
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());
    if (d->remoteSetupState() == RemoteSetupRequested)
        d->setRemoteSetupState(RemoteSetupCancelled);

809
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
810
    setState(EngineSetupFailed);
hjk's avatar
hjk committed
811
    if (isMasterEngine() && runControl())
812
        runControl()->startFailed();
hjk's avatar
hjk committed
813
    setState(DebuggerFinished);
hjk's avatar
hjk committed
814
815
}

816
void DebuggerEngine::notifyEngineSetupOk()
817
{
hjk's avatar
hjk committed
818
    showMessage(_("NOTE: ENGINE SETUP OK"));
819
820
821
822
    QTC_ASSERT(d->remoteSetupState() == RemoteSetupNone
               || d->remoteSetupState() == RemoteSetupSucceeded,
               qDebug() << this << "remoteSetupState" << d->remoteSetupState());

823
    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << this << state());
824
    setState(EngineSetupOk);
hjk's avatar
hjk committed
825
    showMessage(_("QUEUE: SETUP INFERIOR"));
826
    if (isMasterEngine())
827
828
829
830
831
        d->queueSetupInferior();
}

void DebuggerEngine::setupSlaveInferior()
{
832
    QTC_CHECK(state() == EngineSetupOk);
833
    d->queueSetupInferior();
834
835
}

hjk's avatar
hjk committed
836
void DebuggerEnginePrivate::doSetupInferior()
837
{
838
    m_engine->showMessage(_("CALL: SETUP INFERIOR"));
839
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << m_engine << state());
840
    m_progress.setProgressValue(250);
hjk's avatar
hjk committed
841
842
843
844
845
    m_engine->setupInferior();
}

void DebuggerEngine::notifyInferiorSetupFailed()
{
hjk's avatar
hjk committed
846
    showMessage(_("NOTE: INFERIOR SETUP FAILED"));
847
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
hjk's avatar
hjk committed
848
    setState(InferiorSetupFailed);
849
850
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
851
852
853
854
}

void DebuggerEngine::notifyInferiorSetupOk()
{
hjk's avatar
hjk committed
855
    showMessage(_("NOTE: INFERIOR SETUP OK"));
856
857
858
859
    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << this << state());
    setState(InferiorSetupOk);
    if (isMasterEngine())
        d->queueRunEngine();
hjk's avatar
hjk committed
860
861
}

862
863
864
void DebuggerEngine::runSlaveEngine()
{
    QTC_ASSERT(isSlaveEngine(), return);
865
    QTC_CHECK(state() == InferiorSetupOk);
866
867
868
    d->queueRunEngine();
}

hjk's avatar
hjk committed
869
870
void DebuggerEnginePrivate::doRunEngine()
{
hjk's avatar
hjk committed
871
    m_engine->showMessage(_("CALL: RUN ENGINE"));
872
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << m_engine << state());
873
    m_progress.setProgressValue(300);
hjk's avatar
hjk committed
874
875
876
    m_engine->runEngine();
}

hjk's avatar
hjk committed
877
878
void DebuggerEngine::notifyInferiorUnrunnable()
{
hjk's avatar
hjk committed
879
    showMessage(_("NOTE: INFERIOR UNRUNNABLE"));
880
881
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
882
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
883
884
885
886
887
    setState(InferiorUnrunnable);
}

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
888
    showMessage(_("NOTE: ENGINE RUN FAILED"));
889
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
890
891
892
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
893
    setState(EngineRunFailed);
894
895
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
896
897
}

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
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
938
939
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
940
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
941
942
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
943
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
944
    setState(InferiorRunOk);
hjk's avatar
hjk committed
945
946
947
948
}

void DebuggerEngine::notifyEngineRunAndInferiorStopOk()
{
hjk's avatar
hjk committed
949
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR STOP OK"));
950
951
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
952
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
953
    setState(InferiorStopOk);
hjk's avatar
hjk committed
954
955
956
957
}

void DebuggerEngine::notifyInferiorRunRequested()
{
hjk's avatar
hjk committed
958
    showMessage(_("NOTE: INFERIOR RUN REQUESTED"));
959
    QTC_ASSERT(state() == InferiorStopOk, qDebug() << this << state());
hjk's avatar
hjk committed
960
961
962
963
964
    setState(InferiorRunRequested);
}

void DebuggerEngine::notifyInferiorRunOk()
{
hjk's avatar
hjk committed
965
    showMessage(_("NOTE: INFERIOR RUN OK"));
966
967
968
    // Transition from StopRequested can happen sin remotegdbadapter.
    QTC_ASSERT(state() == InferiorRunRequested
        || state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
969
970
971
972
973
    setState(InferiorRunOk);
}

void DebuggerEngine::notifyInferiorRunFailed()
{
hjk's avatar
hjk committed
974
    showMessage(_("NOTE: INFERIOR RUN FAILED"));
975
    QTC_ASSERT(state() == InferiorRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
976
977
    setState(InferiorRunFailed);
    setState(InferiorStopOk);
hjk's avatar
hjk committed
978
979
    if (isDying())
        d->queueShutdownInferior();
hjk's avatar
hjk committed
980
981
982
983
}

void DebuggerEngine::notifyInferiorStopOk()
{
hjk's avatar
hjk committed
984
985
    showMessage(_("NOTE: INFERIOR STOP OK"));
    // Ignore spurious notifications after we are set to die.
hjk's avatar
hjk committed
986
    if (isDying()) {
hjk's avatar
hjk committed
987
988
989
990
991
992
993
994
995
996
997
998
999
        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
1000
    }
1001
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
1002
    setState(InferiorStopOk);
hjk's avatar
hjk committed
1003
1004
}

hjk's avatar
hjk committed
1005
void DebuggerEngine::notifyInferiorSpontaneousStop()
1006
{
1007
    showMessage(_("NOTE: INFERIOR SPONTANEOUS STOP"));
1008
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << this << state());
1009
    setState(InferiorStopOk);
1010
1011
}

hjk's avatar
hjk committed
1012
void DebuggerEngine::notifyInferiorStopFailed()
1013
{
hjk's avatar
hjk committed
1014
    showMessage(_("NOTE: INFERIOR STOP FAILED"));
1015
    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << this << state());
hjk's avatar
hjk committed
1016
    setState(InferiorStopFailed);
1017
1018
    if (isMasterEngine())
        d->queueShutdownEngine();
1019
1020
1021
1022
}

void DebuggerEnginePrivate::doInterruptInferior()
{
1023
1024
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorRunOk, qDebug() << m_engine << state());
hjk's avatar
hjk committed
1025
    m_engine->setState(InferiorStopRequested);
hjk's avatar
hjk committed
1026
    m_engine->showMessage(_("CALL: INTERRUPT INFERIOR"));
1027
1028
1029
    m_engine->interruptInferior();
}

hjk's avatar
hjk committed
1030
1031
void DebuggerEnginePrivate::doShutdownInferior()
{
1032
1033
    //QTC_ASSERT(isMasterEngine(), return);
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << m_engine << state());
1034
    resetLocation();
hjk's avatar
hjk committed
1035
    m_targetState = DebuggerFinished;
hjk's avatar
hjk committed
1036
    m_engine->showMessage(_("CALL: SHUTDOWN INFERIOR"));
hjk's avatar
hjk committed
1037
1038
1039
1040
1041
1042
    m_engine->shutdownInferior();
}

void DebuggerEngine::notifyInferiorShutdownOk()
{
    showMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));