lldbengine.cpp 45.7 KB
Newer Older
1
2
/****************************************************************************
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4
5
6
7
8
9
10
11
12
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
Eike Ziller's avatar
Eike Ziller committed
13
14
** conditions see http://www.qt.io/licensing.  For further information
** use the contact form at http://www.qt.io/contact-us.
15
16
17
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
Eike Ziller's avatar
Eike Ziller committed
18
19
20
21
22
23
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
25
26
27
28
29
30
31
32
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "lldbengine.h"

33
34
35
#include <debugger/debuggeractions.h>
#include <debugger/debuggercore.h>
#include <debugger/debuggerdialogs.h>
Fawzi Mohamed's avatar
Fawzi Mohamed committed
36
#include <debugger/debuggerinternalconstants.h>
37
#include <debugger/debuggermainwindow.h>
38
39
40
41
#include <debugger/debuggerprotocol.h>
#include <debugger/debuggerstartparameters.h>
#include <debugger/debuggerstringutils.h>
#include <debugger/debuggertooltipmanager.h>
42

43
44
45
46
47
48
49
50
51
#include <debugger/breakhandler.h>
#include <debugger/disassemblerlines.h>
#include <debugger/moduleshandler.h>
#include <debugger/registerhandler.h>
#include <debugger/stackhandler.h>
#include <debugger/sourceutils.h>
#include <debugger/threadshandler.h>
#include <debugger/watchhandler.h>
#include <debugger/watchutils.h>
52

53
#include <coreplugin/messagebox.h>
54
55
56
#include <coreplugin/idocument.h>
#include <coreplugin/icore.h>

hjk's avatar
hjk committed
57
58
59
60
61
62
63
#include <texteditor/texteditor.h>

#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <utils/qtcprocess.h>

#include <QApplication>
64
65
66
67
68
69
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QTimer>
#include <QToolTip>
hjk's avatar
hjk committed
70
#include <QVariant>
71

hjk's avatar
hjk committed
72
using namespace Core;
hjk's avatar
hjk committed
73
74
using namespace Utils;

75
76
77
78
79
80
81
82
83
84
namespace Debugger {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
// LldbEngine
//
///////////////////////////////////////////////////////////////////////

LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters)
85
    : DebuggerEngine(startParameters), m_continueAtNextSpontaneousStop(false)
86
{
87
    m_lastAgentId = 0;
hjk's avatar
hjk committed
88
    m_lastToken = 0;
89
    setObjectName(QLatin1String("LldbEngine"));
90

hjk's avatar
hjk committed
91
92
93
94
    if (startParameters.useTerminal) {
        #ifdef Q_OS_WIN
            // Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
            if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
hjk's avatar
hjk committed
95
                m_stubProc.setMode(ConsoleProcess::Suspend);
hjk's avatar
hjk committed
96
            else
hjk's avatar
hjk committed
97
                m_stubProc.setMode(ConsoleProcess::Debug);
hjk's avatar
hjk committed
98
        #else
hjk's avatar
hjk committed
99
100
            m_stubProc.setMode(ConsoleProcess::Debug);
            m_stubProc.setSettings(ICore::settings());
hjk's avatar
hjk committed
101
102
103
        #endif
    }

hjk's avatar
hjk committed
104
105
106
107
108
109
110
111
112
113
    connect(action(AutoDerefPointers), &SavedAction::valueChanged,
            this, &LldbEngine::updateLocals);
    connect(action(CreateFullBacktrace), &QAction::triggered,
            this, &LldbEngine::createFullBacktrace);
    connect(action(UseDebuggingHelpers), &SavedAction::valueChanged,
            this, &LldbEngine::updateLocals);
    connect(action(UseDynamicType), &SavedAction::valueChanged,
            this, &LldbEngine::updateLocals);
    connect(action(IntelFlavor), &SavedAction::valueChanged,
            this, &LldbEngine::updateAll);
114
115
116
}

LldbEngine::~LldbEngine()
hjk's avatar
hjk committed
117
118
119
120
{
    m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
}

121

hjk's avatar
hjk committed
122
void LldbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages)
123
{
hjk's avatar
hjk committed
124
    runCommand(Command("executeDebuggerCommand").arg("command", command));
125
126
}

hjk's avatar
hjk committed
127
void LldbEngine::runCommand(const Command &command)
128
129
{
    QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll());
hjk's avatar
hjk committed
130
131
    ++m_lastToken;
    QByteArray token = QByteArray::number(m_lastToken);
132
133
    QByteArray cmd = "{\"cmd\":\"" + command.function + "\","
        + command.args + "\"token\":" + token + "}\n";
hjk's avatar
hjk committed
134
    showMessage(_(token + cmd), LogInput);
135
    m_lldbProc.write(cmd);
136
137
}

138
139
140
141
142
void LldbEngine::debugLastCommand()
{
    runCommand(m_lastDebuggableCommand);
}

143
144
145
void LldbEngine::shutdownInferior()
{
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
146
    runCommand(Command("shutdownInferior"));
147
148
149
150
151
152
}

void LldbEngine::shutdownEngine()
{
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
    m_lldbProc.kill();
hjk's avatar
hjk committed
153
154
    if (startParameters().useTerminal)
        m_stubProc.stop();
155
    notifyEngineShutdownOk();
156
157
}

158
159
160
161
162
163
164
165
166
167
168
169
170
void LldbEngine::abortDebugger()
{
    if (targetState() == DebuggerFinished) {
        // We already tried. Try harder.
        showMessage(_("ABORTING DEBUGGER. SECOND TIME."));
        m_lldbProc.kill();
    } else {
        // Be friendly the first time. This will change targetState().
        showMessage(_("ABORTING DEBUGGER. FIRST TIME."));
        quitDebugger();
    }
}

hjk's avatar
hjk committed
171
172
173
174
175
176
177
// FIXME: Merge with GdbEngine/QtcProcess
bool LldbEngine::prepareCommand()
{
    if (HostOsInfo::isWindowsHost()) {
        DebuggerStartParameters &sp = startParameters();
        QtcProcess::SplitError perr;
        sp.processArgs = QtcProcess::prepareArgs(sp.processArgs, &perr,
hjk's avatar
hjk committed
178
                                                 HostOsInfo::hostOs(),
hjk's avatar
hjk committed
179
                    &sp.environment, &sp.workingDirectory).toWindowsArgs();
hjk's avatar
hjk committed
180
        if (perr != QtcProcess::SplitOk) {
hjk's avatar
hjk committed
181
182
183
184
185
186
187
188
189
            // perr == BadQuoting is never returned on Windows
            // FIXME? QTCREATORBUG-2809
            notifyEngineSetupFailed();
            return false;
        }
    }
    return true;
}

190
191
void LldbEngine::setupEngine()
{
hjk's avatar
hjk committed
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    if (startParameters().useTerminal) {
        QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
        showMessage(_("TRYING TO START ADAPTER"));

    // Currently, adapters are not re-used
    //    // We leave the console open, so recycle it now.
    //    m_stubProc.blockSignals(true);
    //    m_stubProc.stop();
    //    m_stubProc.blockSignals(false);

        if (!prepareCommand()) {
            notifyEngineSetupFailed();
            return;
        }

        m_stubProc.setWorkingDirectory(startParameters().workingDirectory);
        // Set environment + dumper preload.
        m_stubProc.setEnvironment(startParameters().environment);

hjk's avatar
hjk committed
211
212
213
        connect(&m_stubProc, &ConsoleProcess::processError, this, &LldbEngine::stubError);
        connect(&m_stubProc, &ConsoleProcess::processStarted, this, &LldbEngine::stubStarted);
        connect(&m_stubProc, &ConsoleProcess::stubStopped, this, &LldbEngine::stubExited);
hjk's avatar
hjk committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
        // FIXME: Starting the stub implies starting the inferior. This is
        // fairly unclean as far as the state machine and error reporting go.

        if (!m_stubProc.start(startParameters().executable,
                             startParameters().processArgs)) {
            // Error message for user is delivered via a signal.
            //handleAdapterStartFailed(QString());
            notifyEngineSetupFailed();
            return;
        }

    } else {
        QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
        if (startParameters().remoteSetupNeeded)
            notifyEngineRequestRemoteSetup();
        else
            startLldb();
    }
Fawzi Mohamed's avatar
Fawzi Mohamed committed
232
}
233

Fawzi Mohamed's avatar
Fawzi Mohamed committed
234
235
void LldbEngine::startLldb()
{
236
    m_lldbCmd = startParameters().debuggerCommand;
hjk's avatar
hjk committed
237
238
239
240
241
242
243
244
245
246
247
    connect(&m_lldbProc, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error),
            this, &LldbEngine::handleLldbError);
    connect(&m_lldbProc, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
            this, &LldbEngine::handleLldbFinished);
    connect(&m_lldbProc, &QProcess::readyReadStandardOutput,
            this, &LldbEngine::readLldbStandardOutput);
    connect(&m_lldbProc, &QProcess::readyReadStandardError,
            this, &LldbEngine::readLldbStandardError);

    connect(this, &LldbEngine::outputReady,
            this, &LldbEngine::handleResponse, Qt::QueuedConnection);
248

249
250
    QStringList args;
    args.append(_("-i"));
hjk's avatar
hjk committed
251
    args.append(ICore::resourcePath() + _("/debugger/lldbbridge.py"));
252
    args.append(m_lldbCmd);
253
    showMessage(_("STARTING LLDB: python ") + args.join(QLatin1Char(' ')));
254
    m_lldbProc.setEnvironment(startParameters().environment.toStringList());
Eike Ziller's avatar
Eike Ziller committed
255
256
    if (!startParameters().workingDirectory.isEmpty())
        m_lldbProc.setWorkingDirectory(startParameters().workingDirectory);
257

258
    m_lldbProc.start(_("python"), args);
259
260

    if (!m_lldbProc.waitForStarted()) {
261
        const QString msg = tr("Unable to start LLDB \"%1\": %2")
262
            .arg(m_lldbCmd, m_lldbProc.errorString());
263
264
        notifyEngineSetupFailed();
        showMessage(_("ADAPTER START FAILED"));
265
        if (!msg.isEmpty())
hjk's avatar
hjk committed
266
            ICore::showWarningWithOptions(tr("Adapter start failed."), msg);
267
268
269
270
271
    }
}

void LldbEngine::setupInferior()
{
272
    const DebuggerStartParameters &sp = startParameters();
273

hjk's avatar
hjk committed
274
    const QString path = stringSetting(ExtraDumperFile);
275
    if (!path.isEmpty()) {
276
277
278
        Command cmd("addExtraDumper");
        cmd.arg("path", path.toUtf8());
        runCommand(cmd);
279
280
    }

hjk's avatar
hjk committed
281
    const QString commands = stringSetting(ExtraDumperCommands);
282
283
284
285
286
287
    if (!commands.isEmpty()) {
        Command cmd("executeDebuggerCommand");
        cmd.arg(commands.toUtf8());
        runCommand(cmd);
    }

288
    QString executable;
hjk's avatar
hjk committed
289
290
291
    QtcProcess::Arguments args;
    QtcProcess::prepareCommand(QFileInfo(sp.executable).absoluteFilePath(),
                               sp.processArgs, &executable, &args);
292

293
    Command cmd("setupInferior");
294
    cmd.arg("executable", executable);
295
    cmd.arg("breakOnMain", sp.breakOnMain);
hjk's avatar
hjk committed
296
    cmd.arg("useTerminal", sp.useTerminal);
297
    cmd.arg("startMode", sp.startMode);
hjk's avatar
hjk committed
298

299
    cmd.beginList("processArgs");
300
    foreach (const QString &arg, args.toUnixArgs())
301
302
        cmd.arg(arg.toUtf8().toHex());
    cmd.endList();
303

hjk's avatar
hjk committed
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
    if (sp.useTerminal) {
        QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
        const qint64 attachedPID = m_stubProc.applicationPID();
        const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID();
        const QString msg = (attachedMainThreadID != -1)
                ? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
                : QString::fromLatin1("Attaching to %1").arg(attachedPID);
        showMessage(msg, LogMisc);
        cmd.arg("attachPid", attachedPID);

    } else {

        cmd.arg("startMode", sp.startMode);
        // it is better not to check the start mode on the python sid (as we would have to duplicate the
        // enum values), and thus we assume that if the sp.attachPID is valid we really have to attach
        QTC_CHECK(sp.attachPID <= 0 || (sp.startMode == AttachCrashedExternal
                                    || sp.startMode == AttachExternal));
        cmd.arg("attachPid", sp.attachPID);
        cmd.arg("sysRoot", sp.deviceSymbolsRoot.isEmpty() ? sp.sysRoot : sp.deviceSymbolsRoot);
        cmd.arg("remoteChannel", ((sp.startMode == AttachToRemoteProcess
                                   || sp.startMode == AttachToRemoteServer)
                                  ? sp.remoteChannel : QString()));
        cmd.arg("platform", sp.platform);
        QTC_CHECK(!sp.continueAfterAttach || (sp.startMode == AttachToRemoteProcess
                                              || sp.startMode == AttachExternal
                                              || sp.startMode == AttachToRemoteServer));
        m_continueAtNextSpontaneousStop = false;
    }

333
    runCommand(cmd);
334
335
336
337
338
}

void LldbEngine::runEngine()
{
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
339

hjk's avatar
hjk committed
340
341
    Command cmd("handleBreakpoints");
    if (attemptBreakpointSynchronizationHelper(&cmd)) {
342
        runEngine2();
hjk's avatar
hjk committed
343
344
345
346
    } else {
        cmd.arg("continuation", "runEngine2");
        runCommand(cmd);
    }
347
348
349
350
}

void LldbEngine::runEngine2()
{
351
    showStatusMessage(tr("Running requested..."), 5000);
352
    runCommand("runEngine");
353
354
355
356
357
}

void LldbEngine::interruptInferior()
{
    showStatusMessage(tr("Interrupt requested..."), 5000);
358
    runCommand("interruptInferior");
359
360
}

361
362
363
364
void LldbEngine::executeStep()
{
    resetLocation();
    notifyInferiorRunRequested();
365
    runCommand("executeStep");
366
367
}

368
369
370
371
void LldbEngine::executeStepI()
{
    resetLocation();
    notifyInferiorRunRequested();
372
    runCommand("executeStepI");
373
374
375
376
377
378
}

void LldbEngine::executeStepOut()
{
    resetLocation();
    notifyInferiorRunRequested();
379
    runCommand("executeStepOut");
380
381
382
383
384
385
}

void LldbEngine::executeNext()
{
    resetLocation();
    notifyInferiorRunRequested();
386
    runCommand("executeNext");
387
388
389
390
391
392
}

void LldbEngine::executeNextI()
{
    resetLocation();
    notifyInferiorRunRequested();
393
    runCommand("executeNextI");
394
395
396
397
398
399
}

void LldbEngine::continueInferior()
{
    resetLocation();
    notifyInferiorRunRequested();
400
    runCommand("continueInferior");
401
402
}

403
void LldbEngine::handleResponse(const QByteArray &response)
404
{
405
406
    GdbMi all;
    all.fromStringMultiple(response);
407

408
409
410
411
412
413
    foreach (const GdbMi &item, all.children()) {
        const QByteArray name = item.name();
        if (name == "data")
            refreshLocals(item);
        else if (name == "stack")
            refreshStack(item);
414
415
416
417
        else if (name == "stack-position")
            refreshStackPosition(item);
        else if (name == "stack-top")
            refreshStackTop(item);
418
419
420
421
422
423
424
425
426
427
428
429
        else if (name == "registers")
            refreshRegisters(item);
        else if (name == "threads")
            refreshThreads(item);
        else if (name == "typeinfo")
            refreshTypeInfo(item);
        else if (name == "state")
            refreshState(item);
        else if (name == "location")
            refreshLocation(item);
        else if (name == "modules")
            refreshModules(item);
430
431
        else if (name == "symbols")
            refreshSymbols(item);
432
433
434
435
436
437
        else if (name == "breakpoint-added")
            refreshAddedBreakpoint(item);
        else if (name == "breakpoint-changed")
            refreshChangedBreakpoint(item);
        else if (name == "breakpoint-removed")
            refreshRemovedBreakpoint(item);
438
439
        else if (name == "output")
            refreshOutput(item);
440
441
        else if (name == "disassembly")
            refreshDisassembly(item);
442
443
        else if (name == "memory")
            refreshMemory(item);
444
445
        else if (name == "continuation")
            runContinuation(item);
446
447
        else if (name == "full-backtrace")
            showFullBacktrace(item);
hjk's avatar
hjk committed
448
449
450
451
452
453
        else if (name == "statusmessage") {
            QString msg = QString::fromUtf8(item.data());
            if (msg.size())
                msg[0] = msg.at(0).toUpper();
            showStatusMessage(msg);
        }
454
455
456
    }
}

457
458
void LldbEngine::showFullBacktrace(const GdbMi &data)
{
459
    Internal::openTextEditor(_("Backtrace $"),
460
461
462
        QString::fromUtf8(QByteArray::fromHex(data.data())));
}

463
464
465
466
void LldbEngine::runContinuation(const GdbMi &data)
{
    const QByteArray target = data.data();
    QMetaObject::invokeMethod(this, target, Qt::QueuedConnection);
467
468
}

469
470
void LldbEngine::executeRunToLine(const ContextData &data)
{
471
472
    resetLocation();
    notifyInferiorRunRequested();
hjk's avatar
hjk committed
473
474
475
476
477
    Command cmd("executeRunToLocation");
    cmd.arg("file", data.fileName);
    cmd.arg("line", data.lineNumber);
    cmd.arg("address", data.address);
    runCommand(cmd);
478
479
480
481
}

void LldbEngine::executeRunToFunction(const QString &functionName)
{
482
483
    resetLocation();
    notifyInferiorRunRequested();
hjk's avatar
hjk committed
484
    runCommand(Command("executeRunToFunction").arg("function", functionName));
485
486
487
488
}

void LldbEngine::executeJumpToLine(const ContextData &data)
{
489
490
    resetLocation();
    notifyInferiorRunRequested();
491
492
493
494
495
    Command cmd("executeJumpToLocation");
    cmd.arg("file", data.fileName);
    cmd.arg("line", data.lineNumber);
    cmd.arg("address", data.address);
    runCommand(cmd);
496
497
498
499
500
501
502
503
}

void LldbEngine::activateFrame(int frameIndex)
{
    resetLocation();
    if (state() != InferiorStopOk && state() != InferiorUnrunnable)
        return;

504
505
506
507
508
509
510
    const int n = stackHandler()->stackSize();
    if (frameIndex == n) {
        Command cmd("reportStack");
        cmd.arg("stacklimit", n * 10 + 3);
        runCommand(cmd);
        return;
    }
511
512
513
514
515

    Command cmd("activateFrame");
    cmd.arg("index", frameIndex);
    cmd.arg("thread", threadsHandler()->currentThread().raw());
    runCommand(cmd);
516

517
518
    reloadRegisters();
    updateLocals();
519
520
521
522
}

void LldbEngine::selectThread(ThreadId threadId)
{
hjk's avatar
hjk committed
523
    runCommand(Command("selectThread").arg("id", threadId.raw()));
524
525
}

526
bool LldbEngine::acceptsBreakpoint(Breakpoint bp) const
527
{
528
    return bp.parameters().isCppBreakpoint() && startParameters().startMode != AttachCore;
529
530
}

hjk's avatar
hjk committed
531
bool LldbEngine::attemptBreakpointSynchronizationHelper(Command *cmd)
532
533
534
{
    BreakHandler *handler = breakHandler();

535
    foreach (Breakpoint bp, handler->unclaimedBreakpoints()) {
536
        // Take ownership of the breakpoint. Requests insertion.
537
        if (acceptsBreakpoint(bp)) {
538
            showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2")
539
540
                .arg(bp.id().toString()).arg(bp.state()));
            bp.setEngine(this);
541
542
        } else {
            showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE")
543
                .arg(bp.id().toString()).arg(bp.state()));
544
545
546
547
        }
    }

    bool done = true;
hjk's avatar
hjk committed
548
    cmd->beginList("bkpts");
549
550
551
    foreach (Breakpoint bp, handler->engineBreakpoints(this)) {
        const BreakpointResponse &response = bp.response();
        const BreakpointState bpState = bp.state();
552
        switch (bpState) {
553
554
555
556
557
558
        case BreakpointNew:
            // Should not happen once claimed.
            QTC_CHECK(false);
            break;
        case BreakpointInsertRequested:
            done = false;
hjk's avatar
hjk committed
559
560
            cmd->beginGroup()
                    .arg("operation", "add")
561
562
563
564
565
566
567
568
569
570
571
                    .arg("modelid", bp.id().toByteArray())
                    .arg("type", bp.type())
                    .arg("ignorecount", bp.ignoreCount())
                    .arg("condition", bp.condition().toHex())
                    .arg("function", bp.functionName().toUtf8())
                    .arg("oneshot", bp.isOneShot())
                    .arg("enabled", bp.isEnabled())
                    .arg("file", bp.fileName().toUtf8())
                    .arg("line", bp.lineNumber())
                    .arg("address", bp.address())
                    .arg("expression", bp.expression())
hjk's avatar
hjk committed
572
                    .endGroup();
573
            bp.notifyBreakpointInsertProceeding();
574
575
576
            break;
        case BreakpointChangeRequested:
            done = false;
hjk's avatar
hjk committed
577
578
            cmd->beginGroup()
                    .arg("operation", "change")
579
                    .arg("modelid", bp.id().toByteArray())
hjk's avatar
hjk committed
580
                    .arg("lldbid", response.id.toByteArray())
581
582
583
584
585
586
587
588
589
590
                    .arg("type", bp.type())
                    .arg("ignorecount", bp.ignoreCount())
                    .arg("condition", bp.condition().toHex())
                    .arg("function", bp.functionName().toUtf8())
                    .arg("oneshot", bp.isOneShot())
                    .arg("enabled", bp.isEnabled())
                    .arg("file", bp.fileName().toUtf8())
                    .arg("line", bp.lineNumber())
                    .arg("address", bp.address())
                    .arg("expression", bp.expression())
hjk's avatar
hjk committed
591
                    .endGroup();
592
            bp.notifyBreakpointChangeProceeding();
593
594
595
            break;
        case BreakpointRemoveRequested:
            done = false;
hjk's avatar
hjk committed
596
597
            cmd->beginGroup()
                    .arg("operation", "remove")
598
                    .arg("modelid", bp.id().toByteArray())
hjk's avatar
hjk committed
599
600
                    .arg("lldbid", response.id.toByteArray())
                    .endGroup();
601
            bp.notifyBreakpointRemoveProceeding();
602
603
604
605
606
607
            break;
        case BreakpointChangeProceeding:
        case BreakpointInsertProceeding:
        case BreakpointRemoveProceeding:
        case BreakpointInserted:
        case BreakpointDead:
608
            QTC_ASSERT(false, qDebug() << "UNEXPECTED STATE" << bpState << "FOR BP " << bp.id());
609
610
            break;
        default:
611
            QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << bpState << "FOR BP" << bp.id());
612
613
        }
    }
hjk's avatar
hjk committed
614
    cmd->endList();
615
616
617
618
619
620
621
622
623
624
    return done;
}

void LldbEngine::attemptBreakpointSynchronization()
{
    showMessage(_("ATTEMPT BREAKPOINT SYNCHRONIZATION"));
    if (!stateAcceptsBreakpointChanges()) {
        showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE"));
        return;
    }
625

hjk's avatar
hjk committed
626
627
    Command cmd("handleBreakpoints");
    if (!attemptBreakpointSynchronizationHelper(&cmd)) {
628
        showMessage(_("BREAKPOINTS ARE NOT FULLY SYNCHRONIZED"));
hjk's avatar
hjk committed
629
        runCommand(cmd);
630
631
632
633
    } else {
        showMessage(_("BREAKPOINTS ARE SYNCHRONIZED"));
    }
}
634

635
void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
636
637
{
    BreakHandler *handler = breakHandler();
638
    BreakpointResponseId rid = BreakpointResponseId(bkpt["lldbid"].data());
639
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
640
641
642
643
    Breakpoint bp = handler->breakpointById(id);
    if (!bp.isValid())
        bp = handler->findBreakpointByResponseId(rid);
    BreakpointResponse response = bp.response();
644
645
646
647
    if (added)
        response.id = rid;
    QTC_CHECK(response.id == rid);
    response.address = 0;
648
649
    response.enabled = bkpt["enabled"].toInt();
    response.ignoreCount = bkpt["ignorecount"].toInt();
650
    response.condition = QByteArray::fromHex(bkpt["condition"].data());
651
    response.hitCount = bkpt["hitcount"].toInt();
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
    response.fileName = bkpt["file"].toUtf8();
    response.lineNumber = bkpt["line"].toInt();

    GdbMi locations = bkpt["locations"];
    const int numChild = locations.children().size();
    if (numChild > 1) {
        foreach (const GdbMi &location, locations.children()) {
            const int locid = location["locid"].toInt();
            BreakpointResponse sub;
            sub.id = BreakpointResponseId(rid.majorPart(), locid);
            sub.type = response.type;
            sub.address = location["addr"].toAddress();
            sub.functionName = location["func"].toUtf8();
            sub.fileName = location["file"].toUtf8();
            sub.lineNumber = location["line"].toInt();
667
            bp.insertSubBreakpoint(sub);
668
        }
669
670
671
672
    } else if (numChild == 1) {
        const GdbMi location = locations.childAt(0);
        response.address = location["addr"].toAddress();
        response.functionName = location["func"].toUtf8();
673
    } else {
674
675
        // This can happen for pending breakpoints.
        showMessage(_("NO LOCATIONS (YET) FOR BP %1").arg(response.toString()));
676
    }
677
    bp.setResponse(response);
678
    if (added)
679
        bp.notifyBreakpointInsertOk();
680
    else
681
        bp.notifyBreakpointChangeOk();
682
683
}

684
void LldbEngine::refreshDisassembly(const GdbMi &data)
685
686
687
{
    DisassemblerLines result;

688
    int cookie = data["cookie"].toInt();
689
690
691
692
    QPointer<DisassemblerAgent> agent = m_disassemblerAgents.key(cookie);
    if (!agent.isNull()) {
        foreach (const GdbMi &line, data["lines"].children()) {
            DisassemblerLine dl;
693
            dl.address = line["address"].toAddress();
694
695
            dl.data = line["inst"].toUtf8();
            dl.function = line["func-name"].toUtf8();
696
            dl.offset = line["offset"].toInt();
697
698
699
            QByteArray comment = line["comment"].data();
            if (!comment.isEmpty())
                dl.data += QString::fromUtf8(" # " + comment);
700
701
702
            result.appendLine(dl);
        }
        agent->setContents(result);
703
    }
704
}
705

706
707
void LldbEngine::refreshMemory(const GdbMi &data)
{
708
    int cookie = data["cookie"].toInt();
709
    qulonglong addr = data["address"].toAddress();
710
711
712
713
714
715
716
    QPointer<MemoryAgent> agent = m_memoryAgents.key(cookie);
    if (!agent.isNull()) {
        QPointer<QObject> token = m_memoryAgentTokens.value(cookie);
        QTC_ASSERT(!token.isNull(), return);
        QByteArray ba = QByteArray::fromHex(data["contents"].data());
        agent->addLazyData(token.data(), addr, ba);
    }
717
718
}

719
720
721
722
723
724
725
726
727
728
729
730
void LldbEngine::refreshOutput(const GdbMi &output)
{
    QByteArray channel = output["channel"].data();
    QByteArray data = QByteArray::fromHex(output["data"].data());
    LogChannel ch = AppStuff;
    if (channel == "stdout")
        ch = AppOutput;
    else if (channel == "stderr")
        ch = AppError;
    showMessage(QString::fromUtf8(data), ch);
}

731
732
733
void LldbEngine::refreshAddedBreakpoint(const GdbMi &bkpt)
{
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
734
735
    Breakpoint bp = breakHandler()->breakpointById(id);
    QTC_CHECK(bp.state() == BreakpointInsertProceeding);
736
737
738
739
740
741
    updateBreakpointData(bkpt, true);
}

void LldbEngine::refreshChangedBreakpoint(const GdbMi &bkpt)
{
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
742
743
    Breakpoint bp = breakHandler()->breakpointById(id);
    QTC_CHECK(!bp.isValid() || bp.state() == BreakpointChangeProceeding);
744
745
746
747
    updateBreakpointData(bkpt, false);
}

void LldbEngine::refreshRemovedBreakpoint(const GdbMi &bkpt)
748
{
749
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
750
751
752
    Breakpoint bp = breakHandler()->breakpointById(id);
    QTC_CHECK(bp.state() == BreakpointRemoveProceeding);
    bp.notifyBreakpointRemoveOk();
753
754
755
756
757
758
759
760
761
762
763
764
765
}

void LldbEngine::loadSymbols(const QString &moduleName)
{
    Q_UNUSED(moduleName)
}

void LldbEngine::loadAllSymbols()
{
}

void LldbEngine::reloadModules()
{
766
    runCommand("listModules");
767
768
}

769
void LldbEngine::refreshModules(const GdbMi &modules)
770
{
771
772
    ModulesHandler *handler = modulesHandler();
    handler->beginUpdateAll();
773
    foreach (const GdbMi &item, modules.children()) {
774
        Module module;
775
776
        module.modulePath = item["file"].toUtf8();
        module.moduleName = item["name"].toUtf8();
777
        module.symbolsRead = Module::UnknownReadState;
778
        module.startAddress = item["loaded_addr"].toAddress();
779
        module.endAddress = 0; // FIXME: End address not easily available.
780
        handler->updateModule(module);
781
    }
782
    handler->endUpdateAll();
783
784
785
786
}

void LldbEngine::requestModuleSymbols(const QString &moduleName)
{
787
    runCommand(Command("listSymbols").arg("module", moduleName));
788
789
}

790
void LldbEngine::refreshSymbols(const GdbMi &symbols)
791
{
792
    QString moduleName = symbols["module"].toUtf8();
793
794
795
    Symbols syms;
    foreach (const GdbMi &item, symbols["symbols"].children()) {
        Symbol symbol;
796
797
798
799
800
        symbol.address = item["address"].toUtf8();
        symbol.name = item["name"].toUtf8();
        symbol.state = item["state"].toUtf8();
        symbol.section = item["section"].toUtf8();
        symbol.demangled = item["demangled"].toUtf8();
801
802
        syms.append(symbol);
    }
803
   Internal::showModuleSymbols(moduleName, syms);
804
805
}

806

807
808
809
810
811
812
//////////////////////////////////////////////////////////////////////
//
// Tooltip specific stuff
//
//////////////////////////////////////////////////////////////////////

813
814
815
816
817
void LldbEngine::resetLocation()
{
    DebuggerEngine::resetLocation();
}

818
bool LldbEngine::setToolTipExpression(TextEditor::TextEditorWidget *editorWidget, const DebuggerToolTipContext &context)
819
{
820
    if (state() != InferiorStopOk || !isCppEditor(editorWidget)) {
821
822
        //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
        // " OR NOT A CPPEDITOR";
823
824
825
        return false;
    }

826
827
828
    UpdateParameters params;
    params.tryPartial = true;
    params.tooltipOnly = true;
hjk's avatar
hjk committed
829
    params.tooltipExpression = context.expression;
830
    params.varList = context.iname;
831
832
833
    doUpdateLocals(params);

    return true;
834
835
}

836
837
void LldbEngine::updateAll()
{
838
    reloadRegisters();
839
    updateStack();
840
841
    updateLocals();
}
842

843
844
845
846
847
848
849
850
851
852
void LldbEngine::reloadFullStack()
{
    Command cmd("reportStack");
    cmd.arg("stacklimit", -1);
    runCommand(cmd);
}

void LldbEngine::updateStack()
{
    Command cmd("reportStack");
hjk's avatar
hjk committed
853
    cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
854
855
856
    runCommand(cmd);
}

857
858
859
860
861
862
//////////////////////////////////////////////////////////////////////
//
// Watch specific stuff
//
//////////////////////////////////////////////////////////////////////

863
864
void LldbEngine::assignValueInDebugger(const Internal::WatchData *data,
    const QString &expression, const QVariant &value)
865
{
866
867
868
869
870
    Q_UNUSED(data);
    Command cmd("assignValue");
    cmd.arg("exp", expression.toLatin1().toHex());
    cmd.arg("value", value.toString().toLatin1().toHex());
    runCommand(cmd);
871
872
873
874
875
876
}

void LldbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags)
{
    Q_UNUSED(data);
    Q_UNUSED(flags);
877
878
879
880
    updateLocals();
}

void LldbEngine::updateLocals()
881
882
883
884
885
886
{
    UpdateParameters params;
    doUpdateLocals(params);
}

void LldbEngine::doUpdateLocals(UpdateParameters params)
887
{
888
    WatchHandler *handler = watchHandler();
889
890
891
892
893
894
895

    Command cmd("updateData");
    cmd.arg("expanded", handler->expansionRequests());
    cmd.arg("typeformats", handler->typeFormatRequests());
    cmd.arg("formats", handler->individualFormatRequests());

    const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
hjk's avatar
hjk committed
896
    cmd.arg("passexceptions", alwaysVerbose);
hjk's avatar
hjk committed
897
898
899
    cmd.arg("fancy", boolSetting(UseDebuggingHelpers));
    cmd.arg("autoderef", boolSetting(AutoDerefPointers));
    cmd.arg("dyntype", boolSetting(UseDynamicType));
900
901
    cmd.arg("partial", params.tryPartial);
    cmd.arg("tooltiponly", params.tooltipOnly);
hjk's avatar
hjk committed
902
903

    cmd.beginList("watchers");
hjk's avatar
hjk committed
904

905
    // Watchers
hjk's avatar
hjk committed
906
907
908
909
910
911
    QHashIterator<QByteArray, int> it(WatchHandler::watcherNames());
    while (it.hasNext()) {
        it.next();
        cmd.beginGroup()
            .arg("iname", "watch." + QByteArray::number(it.value()))
            .arg("exp", it.key().toHex())
912
913
        .endGroup();
    }
hjk's avatar
hjk committed
914
915
916
917
918
919
920
921

    // Tooltips
    DebuggerToolTipContexts toolTips = DebuggerToolTipManager::pendingTooltips(this);
    foreach (const DebuggerToolTipContext &p, toolTips) {
        cmd.beginGroup()
                .arg("iname", p.iname)
                .arg("exp", p.expression.toLatin1().toHex())
        .endGroup();
hjk's avatar
hjk committed
922
    }
hjk's avatar
hjk committed
923

hjk's avatar
hjk committed
924
925
    cmd.endList();

926
927
    //cmd.arg("resultvarname", m_resultVarName);

928
929
930
    m_lastDebuggableCommand = cmd;
    m_lastDebuggableCommand.args.replace("\"passexceptions\":0", "\"passexceptions\":1");

931
    runCommand(cmd);
932
933

    reloadRegisters();
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
}

void LldbEngine::handleLldbError(QProcess::ProcessError error)
{
    qDebug() << "HANDLE LLDB ERROR";
    showMessage(_("HANDLE LLDB ERROR"));
    switch (error) {
    case QProcess::Crashed:
        break; // will get a processExited() as well
    // impossible case QProcess::FailedToStart:
    case QProcess::ReadError:
    case QProcess::WriteError:
    case QProcess::Timedout:
    default:
        //setState(EngineShutdownRequested, true);
        m_lldbProc.kill();
hjk's avatar
hjk committed
950
        AsynchronousMessageBox::critical(tr("LLDB I/O Error"), errorMessage(error));
951
952
953
954
955
956
957
958
        break;
    }
}

QString LldbEngine::errorMessage(QProcess::ProcessError error) const
{
    switch (error) {
        case QProcess::FailedToStart:
Leena Miettinen's avatar
Leena Miettinen committed
959
            return tr("The LLDB process failed to start. Either the "
960
                "invoked program \"%1\" is missing, or you may have insufficient "
961
                "permissions to invoke the program.")
962
                .arg(m_lldbCmd);
963
        case QProcess::Crashed:
Leena Miettinen's avatar
Leena Miettinen committed
964
            return tr("The LLDB process crashed some time after starting "
965
966
967
968
969
970
971
                "successfully.");
        case QProcess::Timedout:
            return tr("The last waitFor...() function timed out. "
                "The state of QProcess is unchanged, and you can try calling "
                "waitFor...() again.");
        case QProcess::WriteError:
            return tr("An error occurred when attempting to write "
Leena Miettinen's avatar
Leena Miettinen committed
972
                "to the LLDB process. For example, the process may not be running, "
973
974
975
976
977
                "or it may have closed its input channel.");
        case QProcess::ReadError:
            return tr("An error occurred when attempting to read from "
                "the Lldb process. For example, the process may not be running.");
        default:
Friedemann Kleint's avatar
Friedemann Kleint committed
978
            return tr("An unknown error in the LLDB process occurred.") + QLatin1Char(' ');
979
980
981
982
983
984
985
986
987
988
989
990
991
    }
}

void LldbEngine::handleLldbFinished(int code, QProcess::ExitStatus type)
{
    qDebug() << "LLDB FINISHED";
    showMessage(_("LLDB PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
    notifyEngineSpontaneousShutdown();
}

void LldbEngine::readLldbStandardError()
{
    QByteArray err = m_lldbProc.readAllStandardError();
992
993
    qDebug() << "\nLLDB STDERR UNEXPECTED: " << err;
    showMessage(_("Lldb stderr: " + err), LogError);
994
995
996
997
998
}

void LldbEngine::readLldbStandardOutput()
{
    QByteArray out = m_lldbProc.readAllStandardOutput();
999
    showMessage(_("Lldb stdout: " + out));
1000
    m_inbuffer.append(out);
1001
    while (true) {
1002
        int pos = m_inbuffer.indexOf("@\n");
1003
1004
1005
        if (pos == -1)
            break;
        QByteArray response = m_inbuffer.left(pos).trimmed();
1006
        m_inbuffer = m_inbuffer.mid(pos + 2);
1007
1008
1009
1010
        emit outputReady(response);
    }
}

1011
1012
1013
1014
void LldbEngine::refreshLocals(const GdbMi &vars)
{
    //const bool partial = response.cookie.toBool();
    WatchHandler *handler = watchHandler();
1015
    handler->resetValueCache();
1016
1017
1018
1019
1020
    QList<WatchData> list;

    //if (!partial) {
        list.append(*handler->findData("local"));
        list.append(*handler->findData("watch"));
1021
        list.append(*handler->findData("tooltip"));
1022
1023
1024
1025
1026
        list.append(*handler->findData("return"));
    //}

    foreach (const GdbMi &child, vars.children()) {
        WatchData dummy;
1027
1028
        dummy.iname = child["iname"].data();
        GdbMi wname = child["wname"];
1029
        if (wname.isValid()) {
1030
1031
1032
            // Happens (only) for watched expressions.
            dummy.exp = QByteArray::fromHex(wname.data());
            dummy.name = QString::fromUtf8(dummy.exp);
1033
        } else {
1034
            dummy.name = child["name"].toUtf8();
1035
        }
1036
1037
1038
        parseWatchData(handler->expandedINames(), dummy, child, &list);
    }
    handler->insertData(list);
1039

hjk's avatar
hjk committed
1040
    DebuggerToolTipManager::updateEngine(this);
1041
1042
1043
1044
1045
1046
 }

void LldbEngine::refreshStack(const GdbMi &stack)
{
    StackHandler *handler = stackHandler();
    StackFrames frames;
1047
    foreach (const GdbMi &item, stack["frames"].children()) {
1048
        StackFrame frame;
1049
        frame.level = item["level"].toInt();
1050
1051
1052
        frame.file = item["file"].toUtf8();
        frame.function = item["func"].toUtf8();
        frame.from = item["func"].toUtf8();
1053
        frame.line = item["line"].toInt();
1054
        frame.address = item["addr"].toAddress();
1055
1056
1057
        frame.usable = QFileInfo(frame.file).isReadable();
        frames.append(frame);
    }
1058
    bool canExpand = stack["hasmore"].toInt();
hjk's avatar
hjk committed
1059
    action(ExpandStack)->setEnabled(canExpand);
1060
    handler->setFrames(frames, canExpand);
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
}

void LldbEngine::refreshStackPosition(const GdbMi &position)
{
    setStackPosition(position["id"].toInt());
}

void LldbEngine::refreshStackTop(const GdbMi &)
{
    setStackPosition(stackHandler()->firstUsableIndex());
}
1072

1073
1074
1075
1076
void LldbEngine::setStackPosition(int index)
{
    StackHandler *handler = stackHandler();
    handler->setFrames(handler->frames());
1077
    handler->setCurrentIndex(index);
1078
1079
    if (index >= 0 && index < handler->stackSize())
        gotoLocation(handler->frameAt(index));
1080
1081
1082
1083
1084
1085
1086
}

void LldbEngine::refreshRegisters(const GdbMi &registers)
{
    RegisterHandler *handler = registerHandler();
    foreach (const GdbMi &item, registers.children()) {
        Register reg;
1087
1088
        reg.name = item["name"].data();
        reg.value = item["value"].data();
hjk's avatar
hjk committed
1089
1090
1091
        reg.size = item["size"].data().toInt();
        reg.reportedType = item["type"].data();
        handler->updateRegister(reg);
1092
    }
hjk's avatar
hjk committed
1093
    handler->commitUpdates();
1094
}
1095
1096
1097
1098
1099
1100
1101
1102
1103

void LldbEngine::refreshThreads(const GdbMi &threads)
{
    ThreadsHandler *handler = threadsHandler();
    handler->updateThreads(threads);
    if (!handler->currentThread().isValid()) {
        ThreadId other = handler->threadAt(0);
        if (other.isValid())
            selectThread(other);
1104
    }
1105
    updateViews(); // Adjust Threads combobox.
hjk's avatar
hjk committed
1106
1107
}

1108
void LldbEngine::refreshTypeInfo(const GdbMi &typeInfo)