debuggerengine.cpp 55.5 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
    bool m_testsPossible;
David Schulz's avatar
David Schulz committed
318
319
    bool m_breakOnError;
    bool m_foundError;
320
    QStringList m_testContents;
321
322
    TaskHub *m_taskHub;
    QString m_testFileName;
323
324
325
326
327
328
329
330
331
};


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

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

DebuggerEngine::~DebuggerEngine()
{
342
343
    disconnect();
    delete d;
344
345
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

564
565
566
567
    d->m_runControl = runControl;

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

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

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

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

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

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

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


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

623
624
625
626
627
628
    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);
    }
629
630

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

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

646
647
// Called from RunControl.
void DebuggerEngine::handleFinished()
648
{
649
    showMessage(QLatin1String("HANDLE RUNCONTROL FINISHED"));
650
    d->m_runControl = 0;
651
652
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
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
679
680
    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
681
    return debuggerCore()->boolSetting(UseDebuggingHelpers);
682
683
684
685
686
687
688
689
690
}

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

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

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

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

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

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

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

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

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

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

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

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

761
762
763
    case InferiorExitOk:
        return to == InferiorShutdownOk;

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

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

    case DebuggerFinished:
781
        return to == EngineSetupRequested; // Happens on restart.
782
783
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

void DebuggerEngine::notifyEngineRunFailed()
{
hjk's avatar
hjk committed
890
    showMessage(_("NOTE: ENGINE RUN FAILED"));
891
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
892
893
894
    d->m_progress.setProgressValue(900);
    d->m_progress.reportCanceled();
    d->m_progress.reportFinished();
hjk's avatar
hjk committed
895
    setState(EngineRunFailed);
896
897
    if (isMasterEngine())
        d->queueShutdownEngine();
hjk's avatar
hjk committed
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
938
939
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
940
941
void DebuggerEngine::notifyEngineRunAndInferiorRunOk()
{
hjk's avatar
hjk committed
942
    showMessage(_("NOTE: ENGINE RUN AND INFERIOR RUN OK"));
943
944
    d->m_progress.setProgressValue(1000);
    d->m_progress.reportFinished();
945
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << this << state());
hjk's avatar
hjk committed
946
    setState(InferiorRunOk);
hjk's avatar
hjk committed
947
948
949
950
}

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

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

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

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

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

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

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

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

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