lldbengine.cpp 42.1 KB
Newer Older
1
2
/****************************************************************************
**
Eike Ziller's avatar
Eike Ziller committed
3
4
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
5
6
7
8
9
10
11
**
** 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
Eike Ziller's avatar
Eike Ziller committed
12
13
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
Eike Ziller's avatar
Eike Ziller committed
14
** 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
**
Eike Ziller's avatar
Eike Ziller committed
25
26
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
27
28
29
30
31
32
** 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
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
#include <utils/qtcprocess.h>

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

hjk's avatar
hjk committed
70
using namespace Core;
hjk's avatar
hjk committed
71
72
using namespace Utils;

73
74
75
namespace Debugger {
namespace Internal {

76
77
78
79
80
81
static int &currentToken()
{
    static int token = 0;
    return token;
}

82
83
84
85
86
87
///////////////////////////////////////////////////////////////////////
//
// LldbEngine
//
///////////////////////////////////////////////////////////////////////

88
LldbEngine::LldbEngine(const DebuggerRunParameters &startParameters)
89
    : DebuggerEngine(startParameters), m_continueAtNextSpontaneousStop(false)
90
{
91
    m_lastAgentId = 0;
92
    setObjectName(QLatin1String("LldbEngine"));
93

hjk's avatar
hjk committed
94
95
96
97
    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
98
                m_stubProc.setMode(ConsoleProcess::Suspend);
hjk's avatar
hjk committed
99
            else
hjk's avatar
hjk committed
100
                m_stubProc.setMode(ConsoleProcess::Debug);
hjk's avatar
hjk committed
101
        #else
hjk's avatar
hjk committed
102
103
            m_stubProc.setMode(ConsoleProcess::Debug);
            m_stubProc.setSettings(ICore::settings());
hjk's avatar
hjk committed
104
105
106
        #endif
    }

hjk's avatar
hjk committed
107
108
109
110
111
112
113
114
115
116
    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);
117
118
119
}

LldbEngine::~LldbEngine()
hjk's avatar
hjk committed
120
121
{
    m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
122
    m_lldbProc.disconnect();
hjk's avatar
hjk committed
123
124
}

hjk's avatar
hjk committed
125
void LldbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages)
126
{
127
128
129
    DebuggerCommand cmd("executeDebuggerCommand");
    cmd.arg("command", command);
    runCommand(cmd);
130
131
}

132
void LldbEngine::runCommand(const DebuggerCommand &command_)
133
134
{
    QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll());
135
136
137
138
    const int tok = ++currentToken();
    DebuggerCommand command = command_;
    command.arg("token", tok);
    QByteArray token = QByteArray::number(tok);
139
140
    QByteArray cmd  = command.function + "({" + command.args + "})";
    showMessage(_(token + cmd + '\n'), LogInput);
hjk's avatar
hjk committed
141
    m_lldbProc.write("script theDumper." + cmd + "\n");
142
143
}

144
145
146
147
148
void LldbEngine::debugLastCommand()
{
    runCommand(m_lastDebuggableCommand);
}

149
150
151
void LldbEngine::shutdownInferior()
{
    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
152
    runCommand(DebuggerCommand("shutdownInferior"));
153
154
155
156
157
158
}

void LldbEngine::shutdownEngine()
{
    QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
    m_lldbProc.kill();
159
    if (runParameters().useTerminal)
hjk's avatar
hjk committed
160
        m_stubProc.stop();
161
    notifyEngineShutdownOk();
162
163
}

164
165
166
167
168
169
170
171
172
173
174
175
176
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
177
178
179
180
// FIXME: Merge with GdbEngine/QtcProcess
bool LldbEngine::prepareCommand()
{
    if (HostOsInfo::isWindowsHost()) {
181
        DebuggerRunParameters &rp = runParameters();
hjk's avatar
hjk committed
182
        QtcProcess::SplitError perr;
183
        rp.processArgs = QtcProcess::prepareArgs(rp.processArgs, &perr,
hjk's avatar
hjk committed
184
                                                 HostOsInfo::hostOs(),
185
                    nullptr, &rp.workingDirectory).toWindowsArgs();
hjk's avatar
hjk committed
186
        if (perr != QtcProcess::SplitOk) {
hjk's avatar
hjk committed
187
188
189
190
191
192
193
194
195
            // perr == BadQuoting is never returned on Windows
            // FIXME? QTCREATORBUG-2809
            notifyEngineSetupFailed();
            return false;
        }
    }
    return true;
}

196
197
void LldbEngine::setupEngine()
{
198
    if (runParameters().useTerminal) {
hjk's avatar
hjk committed
199
200
201
202
203
204
205
206
207
208
209
210
211
212
        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;
        }

213
        m_stubProc.setWorkingDirectory(runParameters().workingDirectory);
hjk's avatar
hjk committed
214
        // Set environment + dumper preload.
215
        m_stubProc.setEnvironment(runParameters().environment);
hjk's avatar
hjk committed
216

hjk's avatar
hjk committed
217
218
219
        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
220
221
222
        // FIXME: Starting the stub implies starting the inferior. This is
        // fairly unclean as far as the state machine and error reporting go.

223
224
        if (!m_stubProc.start(runParameters().executable,
                             runParameters().processArgs)) {
hjk's avatar
hjk committed
225
226
227
228
229
230
231
232
            // Error message for user is delivered via a signal.
            //handleAdapterStartFailed(QString());
            notifyEngineSetupFailed();
            return;
        }

    } else {
        QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
233
        if (runParameters().remoteSetupNeeded)
hjk's avatar
hjk committed
234
235
236
237
            notifyEngineRequestRemoteSetup();
        else
            startLldb();
    }
Fawzi Mohamed's avatar
Fawzi Mohamed committed
238
}
239

Fawzi Mohamed's avatar
Fawzi Mohamed committed
240
241
void LldbEngine::startLldb()
{
242
    m_lldbCmd = runParameters().debuggerCommand;
hjk's avatar
hjk committed
243
244
245
246
247
248
249
250
251
252
253
    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);
254

255
    showMessage(_("STARTING LLDB: ") + m_lldbCmd);
256
    m_lldbProc.setEnvironment(runParameters().environment);
257
258
    if (!runParameters().workingDirectory.isEmpty())
        m_lldbProc.setWorkingDirectory(runParameters().workingDirectory);
259

260
261
    m_lldbProc.setCommand(m_lldbCmd, QString());
    m_lldbProc.start();
262
263

    if (!m_lldbProc.waitForStarted()) {
264
        const QString msg = tr("Unable to start LLDB \"%1\": %2")
265
            .arg(m_lldbCmd, m_lldbProc.errorString());
266
267
        notifyEngineSetupFailed();
        showMessage(_("ADAPTER START FAILED"));
268
        if (!msg.isEmpty())
hjk's avatar
hjk committed
269
            ICore::showWarningWithOptions(tr("Adapter start failed."), msg);
270
        return;
271
    }
272
273
274
    m_lldbProc.waitForReadyRead(1000);
    m_lldbProc.write("sc print('@\\nlldbstartupok@\\n')\n");
}
275

276
277
278
// FIXME: splitting of startLldb() necessary to support LLDB <= 310 - revert asap
void LldbEngine::startLldbStage2()
{
279
280
281
282
283
284
    showMessage(_("ADAPTER STARTED"));
    showStatusMessage(tr("Setting up inferior..."));

    const QByteArray dumperSourcePath =
        ICore::resourcePath().toLocal8Bit() + "/debugger/";

hjk's avatar
hjk committed
285
286
287
288
    m_lldbProc.write("script sys.path.insert(1, '" + dumperSourcePath + "')\n");
    m_lldbProc.write("script from lldbbridge import *\n");
    m_lldbProc.write("script print(dir())\n");
    m_lldbProc.write("script theDumper = Dumper()\n"); // This triggers reportState("enginesetupok")
289
290
291
292
}

void LldbEngine::setupInferior()
{
293
294
295
296
297
298
299
300
301
    Environment sysEnv = Environment::systemEnvironment();
    Environment runEnv = runParameters().environment;
    foreach (const EnvironmentItem &item, sysEnv.diff(runEnv)) {
        DebuggerCommand cmd("executeDebuggerCommand");
        if (item.unset)
            cmd.arg("command", "settings remove target.env-vars " + item.name.toUtf8());
        else
            cmd.arg("command", "settings set target.env-vars " + item.name.toUtf8() + '=' + item.value.toUtf8());
        runCommand(cmd);
302
303
    }

hjk's avatar
hjk committed
304
    const QString path = stringSetting(ExtraDumperFile);
305
    if (!path.isEmpty() && QFileInfo(path).isReadable()) {
306
        DebuggerCommand cmd("addDumperModule");
307
308
        cmd.arg("path", path.toUtf8());
        runCommand(cmd);
309
310
    }

hjk's avatar
hjk committed
311
    const QString commands = stringSetting(ExtraDumperCommands);
312
    if (!commands.isEmpty()) {
313
        DebuggerCommand cmd("executeDebuggerCommand");
hjk's avatar
hjk committed
314
        cmd.arg("command", commands.toUtf8());
315
316
317
        runCommand(cmd);
    }

318
    DebuggerCommand cmd1("loadDumpers");
hjk's avatar
hjk committed
319
    runCommand(cmd1);
320
321
322
323
324
}

// FIXME: splitting of setupInferior() necessary to support LLDB <= 310 - revert asap
void LldbEngine::setupInferiorStage2()
{
325
    const DebuggerRunParameters &rp = runParameters();
hjk's avatar
hjk committed
326

327
    QString executable;
hjk's avatar
hjk committed
328
    QtcProcess::Arguments args;
329
330
    QtcProcess::prepareCommand(QFileInfo(rp.executable).absoluteFilePath(),
                               rp.processArgs, &executable, &args);
331

332
    DebuggerCommand cmd("setupInferior");
333
    cmd.arg("executable", executable);
334
335
336
    cmd.arg("breakOnMain", rp.breakOnMain);
    cmd.arg("useTerminal", rp.useTerminal);
    cmd.arg("startMode", rp.startMode);
hjk's avatar
hjk committed
337

338
339
340
341
342
343
    cmd.beginList("bkpts");
    foreach (Breakpoint bp, breakHandler()->unclaimedBreakpoints()) {
        if (acceptsBreakpoint(bp)) {
            showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2")
                            .arg(bp.id().toString()).arg(bp.state()));
            bp.setEngine(this);
344
            bp.notifyBreakpointInsertProceeding();
345
            cmd.beginGroup();
346
            bp.addToCommand(&cmd);
347
348
349
350
351
352
353
            cmd.endGroup();
        } else {
            showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE")
                .arg(bp.id().toString()).arg(bp.state()));
        }
    }
    cmd.endList();
354

355
    cmd.beginList("processArgs");
356
    foreach (const QString &arg, args.toUnixArgs())
357
358
        cmd.arg(arg.toUtf8().toHex());
    cmd.endList();
359

360
    if (rp.useTerminal) {
hjk's avatar
hjk committed
361
362
363
364
365
366
367
368
369
370
371
        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 {

372
        cmd.arg("startMode", rp.startMode);
hjk's avatar
hjk committed
373
        // it is better not to check the start mode on the python sid (as we would have to duplicate the
374
375
376
377
378
379
380
381
382
383
384
385
        // enum values), and thus we assume that if the rp.attachPID is valid we really have to attach
        QTC_CHECK(rp.attachPID <= 0 || (rp.startMode == AttachCrashedExternal
                                    || rp.startMode == AttachExternal));
        cmd.arg("attachPid", rp.attachPID);
        cmd.arg("sysRoot", rp.deviceSymbolsRoot.isEmpty() ? rp.sysRoot : rp.deviceSymbolsRoot);
        cmd.arg("remoteChannel", ((rp.startMode == AttachToRemoteProcess
                                   || rp.startMode == AttachToRemoteServer)
                                  ? rp.remoteChannel : QString()));
        cmd.arg("platform", rp.platform);
        QTC_CHECK(!rp.continueAfterAttach || (rp.startMode == AttachToRemoteProcess
                                              || rp.startMode == AttachExternal
                                              || rp.startMode == AttachToRemoteServer));
hjk's avatar
hjk committed
386
387
388
        m_continueAtNextSpontaneousStop = false;
    }

389
    runCommand(cmd);
390
391
392
393
}

void LldbEngine::runEngine()
{
394
    const DebuggerRunParameters &rp = runParameters();
395
    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state(); return);
396
    showStatusMessage(tr("Running requested..."), 5000);
397
    DebuggerCommand cmd("runEngine");
398
399
    if (rp.startMode == AttachCore) {
        cmd.arg("coreFile", rp.coreFile);
400
401
402
        cmd.arg("continuation", "updateAll");
    }
    runCommand(cmd);
403
404
405
406
407
}

void LldbEngine::interruptInferior()
{
    showStatusMessage(tr("Interrupt requested..."), 5000);
408
    runCommand("interruptInferior");
409
410
}

411
412
413
414
void LldbEngine::executeStep()
{
    resetLocation();
    notifyInferiorRunRequested();
415
    runCommand("executeStep");
416
417
}

418
419
420
421
void LldbEngine::executeStepI()
{
    resetLocation();
    notifyInferiorRunRequested();
422
    runCommand("executeStepI");
423
424
425
426
427
428
}

void LldbEngine::executeStepOut()
{
    resetLocation();
    notifyInferiorRunRequested();
429
    runCommand("executeStepOut");
430
431
432
433
434
435
}

void LldbEngine::executeNext()
{
    resetLocation();
    notifyInferiorRunRequested();
436
    runCommand("executeNext");
437
438
439
440
441
442
}

void LldbEngine::executeNextI()
{
    resetLocation();
    notifyInferiorRunRequested();
443
    runCommand("executeNextI");
444
445
446
447
448
449
}

void LldbEngine::continueInferior()
{
    resetLocation();
    notifyInferiorRunRequested();
450
    runCommand("continueInferior");
451
452
}

453
void LldbEngine::handleResponse(const QByteArray &response)
454
{
455
456
    GdbMi all;
    all.fromStringMultiple(response);
457

458
459
    foreach (const GdbMi &item, all.children()) {
        const QByteArray name = item.name();
460
461
        if (name == "all") {
            updateLocalsView(item);
462
            watchHandler()->notifyUpdateFinished();
463
        } else if (name == "dumpers") {
hjk's avatar
hjk committed
464
            watchHandler()->addDumpers(item);
465
466
            setupInferiorStage2();
        } else if (name == "stack")
467
468
469
470
471
            refreshStack(item);
        else if (name == "registers")
            refreshRegisters(item);
        else if (name == "threads")
            refreshThreads(item);
472
473
        else if (name == "current-thread")
            refreshCurrentThread(item);
474
475
476
477
478
479
480
481
        else if (name == "typeinfo")
            refreshTypeInfo(item);
        else if (name == "state")
            refreshState(item);
        else if (name == "location")
            refreshLocation(item);
        else if (name == "modules")
            refreshModules(item);
482
483
        else if (name == "symbols")
            refreshSymbols(item);
484
485
486
487
488
489
        else if (name == "breakpoint-added")
            refreshAddedBreakpoint(item);
        else if (name == "breakpoint-changed")
            refreshChangedBreakpoint(item);
        else if (name == "breakpoint-removed")
            refreshRemovedBreakpoint(item);
490
491
        else if (name == "output")
            refreshOutput(item);
492
493
        else if (name == "disassembly")
            refreshDisassembly(item);
494
495
        else if (name == "memory")
            refreshMemory(item);
496
497
        else if (name == "full-backtrace")
            showFullBacktrace(item);
498
499
        else if (name == "continuation")
            handleContinuation(item);
hjk's avatar
hjk committed
500
501
502
503
504
505
        else if (name == "statusmessage") {
            QString msg = QString::fromUtf8(item.data());
            if (msg.size())
                msg[0] = msg.at(0).toUpper();
            showStatusMessage(msg);
        }
506
507
508
    }
}

509
510
511
512
void LldbEngine::handleContinuation(const GdbMi &data)
{
    if (data.data() == "updateLocals") {
        updateLocals();
513
514
515
516
    } else if (data.data() == "updateAll") {
        updateAll();
    } else {
        QTC_ASSERT(false, qDebug() << "Unknown continuation: " << data.data());
517
518
519
    }
}

520
521
void LldbEngine::showFullBacktrace(const GdbMi &data)
{
522
    Internal::openTextEditor(_("Backtrace $"),
523
524
525
        QString::fromUtf8(QByteArray::fromHex(data.data())));
}

526
527
void LldbEngine::executeRunToLine(const ContextData &data)
{
528
529
    resetLocation();
    notifyInferiorRunRequested();
530
    DebuggerCommand cmd("executeRunToLocation");
hjk's avatar
hjk committed
531
532
533
534
    cmd.arg("file", data.fileName);
    cmd.arg("line", data.lineNumber);
    cmd.arg("address", data.address);
    runCommand(cmd);
535
536
537
538
}

void LldbEngine::executeRunToFunction(const QString &functionName)
{
539
540
    resetLocation();
    notifyInferiorRunRequested();
541
542
543
    DebuggerCommand cmd("executeRunToFunction");
    cmd.arg("function", functionName);
    runCommand(cmd);
544
545
546
547
}

void LldbEngine::executeJumpToLine(const ContextData &data)
{
548
    resetLocation();
549
    DebuggerCommand cmd("executeJumpToLocation");
550
551
552
553
    cmd.arg("file", data.fileName);
    cmd.arg("line", data.lineNumber);
    cmd.arg("address", data.address);
    runCommand(cmd);
554
555
556
557
558
559
560
}

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

561
562
563
    StackHandler *handler = stackHandler();

    const int n = handler->stackSize();
564
    if (frameIndex == n) {
565
        DebuggerCommand cmd("reportStack");
566
        cmd.arg("nativeMixed", isNativeMixedActive());
567
568
569
570
        cmd.arg("stacklimit", n * 10 + 3);
        runCommand(cmd);
        return;
    }
571

572
573
574
575
    QTC_ASSERT(frameIndex < handler->stackSize(), return);
    handler->setCurrentIndex(frameIndex);
    gotoLocation(handler->currentFrame());

576
    DebuggerCommand cmd("activateFrame");
577
578
    cmd.arg("index", frameIndex);
    cmd.arg("thread", threadsHandler()->currentThread().raw());
579
    cmd.arg("continuation", "updateLocals");
580
    runCommand(cmd);
581
582
583
584
}

void LldbEngine::selectThread(ThreadId threadId)
{
585
586
587
588
589
590
591
592
    DebuggerCommand cmd1("selectThread");
    cmd1.arg("id", threadId.raw());
    runCommand(cmd1);

    DebuggerCommand cmd("reportStack");
    cmd.arg("nativeMixed", isNativeMixedActive());
    cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
    cmd.arg("continuation", "updateLocals");
593
    runCommand(cmd);
594
595
}

596
bool LldbEngine::stateAcceptsBreakpointChanges() const
597
{
598
599
600
601
602
603
604
605
606
607
    switch (state()) {
    case InferiorSetupRequested:
    case InferiorRunRequested:
    case InferiorRunOk:
    case InferiorStopRequested:
    case InferiorStopOk:
        return true;
    default:
        return false;
    }
608
609
}

610
bool LldbEngine::acceptsBreakpoint(Breakpoint bp) const
611
{
612
    if (runParameters().startMode == AttachCore)
613
614
        return false;
    // We handle QML breakpoint unless specifically disabled.
615
    if (isNativeMixedEnabled() && !(runParameters().languages & QmlLanguage))
616
617
618
        return true;
    return bp.parameters().isCppBreakpoint();
}
619

620
621
622
void LldbEngine::insertBreakpoint(Breakpoint bp)
{
    DebuggerCommand cmd("insertBreakpoint");
623
    bp.addToCommand(&cmd);
624
    bp.notifyBreakpointInsertProceeding();
625
    runCommand(cmd);
626
627
}

628
void LldbEngine::changeBreakpoint(Breakpoint bp)
629
{
630
631
    const BreakpointResponse &response = bp.response();
    DebuggerCommand cmd("changeBreakpoint");
632
    cmd.arg("lldbid", response.id.toByteArray());
633
    bp.addToCommand(&cmd);
634
635
636
    bp.notifyBreakpointChangeProceeding();
    runCommand(cmd);
}
637

638
639
640
641
642
643
644
645
void LldbEngine::removeBreakpoint(Breakpoint bp)
{
    const BreakpointResponse &response = bp.response();
    DebuggerCommand cmd("removeBreakpoint");
    cmd.arg("modelid", bp.id().toByteArray());
    cmd.arg("lldbid", response.id.toByteArray());
    bp.notifyBreakpointRemoveProceeding();
    runCommand(cmd);
646
}
647

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

    GdbMi locations = bkpt["locations"];
669
    const int numChild = int(locations.children().size());
670
671
672
673
674
675
676
677
678
679
    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();
680
            bp.insertSubBreakpoint(sub);
681
        }
682
683
684
685
    } else if (numChild == 1) {
        const GdbMi location = locations.childAt(0);
        response.address = location["addr"].toAddress();
        response.functionName = location["func"].toUtf8();
686
    } else {
687
688
        // This can happen for pending breakpoints.
        showMessage(_("NO LOCATIONS (YET) FOR BP %1").arg(response.toString()));
689
    }
690
    bp.setResponse(response);
691
    if (added)
692
        bp.notifyBreakpointInsertOk();
693
    else
694
        bp.notifyBreakpointChangeOk();
695
696
}

697
void LldbEngine::refreshDisassembly(const GdbMi &data)
698
699
700
{
    DisassemblerLines result;

701
    int cookie = data["cookie"].toInt();
702
703
704
705
    QPointer<DisassemblerAgent> agent = m_disassemblerAgents.key(cookie);
    if (!agent.isNull()) {
        foreach (const GdbMi &line, data["lines"].children()) {
            DisassemblerLine dl;
706
            dl.address = line["address"].toAddress();
707
708
            dl.data = line["inst"].toUtf8();
            dl.function = line["func-name"].toUtf8();
709
            dl.offset = line["offset"].toInt();
710
711
712
713
            dl.lineNumber = line["line"].toInt();
            dl.fileName = line["file"].toUtf8();
            dl.function = line["function"].toUtf8();
            dl.hunk = line["hunk"].toInt();
714
715
716
            QByteArray comment = line["comment"].data();
            if (!comment.isEmpty())
                dl.data += QString::fromUtf8(" # " + comment);
717
718
719
            result.appendLine(dl);
        }
        agent->setContents(result);
720
    }
721
}
722

723
724
void LldbEngine::refreshMemory(const GdbMi &data)
{
725
    int cookie = data["cookie"].toInt();
726
    qulonglong addr = data["address"].toAddress();
727
728
729
730
731
732
733
    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);
    }
734
735
}

736
737
738
739
740
741
742
743
744
745
746
747
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);
}

748
749
750
void LldbEngine::refreshAddedBreakpoint(const GdbMi &bkpt)
{
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
751
752
    Breakpoint bp = breakHandler()->breakpointById(id);
    QTC_CHECK(bp.state() == BreakpointInsertProceeding);
753
754
755
756
757
758
    updateBreakpointData(bkpt, true);
}

void LldbEngine::refreshChangedBreakpoint(const GdbMi &bkpt)
{
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
759
760
    Breakpoint bp = breakHandler()->breakpointById(id);
    QTC_CHECK(!bp.isValid() || bp.state() == BreakpointChangeProceeding);
761
762
763
764
    updateBreakpointData(bkpt, false);
}

void LldbEngine::refreshRemovedBreakpoint(const GdbMi &bkpt)
765
{
766
    BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
767
768
769
    Breakpoint bp = breakHandler()->breakpointById(id);
    QTC_CHECK(bp.state() == BreakpointRemoveProceeding);
    bp.notifyBreakpointRemoveOk();
770
771
772
773
774
775
776
777
778
779
780
781
782
}

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

void LldbEngine::loadAllSymbols()
{
}

void LldbEngine::reloadModules()
{
783
    runCommand("listModules");
784
785
}

786
void LldbEngine::refreshModules(const GdbMi &modules)
787
{
788
789
    ModulesHandler *handler = modulesHandler();
    handler->beginUpdateAll();
790
    foreach (const GdbMi &item, modules.children()) {
791
        Module module;
792
793
        module.modulePath = item["file"].toUtf8();
        module.moduleName = item["name"].toUtf8();
794
        module.symbolsRead = Module::UnknownReadState;
795
        module.startAddress = item["loaded_addr"].toAddress();
796
        module.endAddress = 0; // FIXME: End address not easily available.
797
        handler->updateModule(module);
798
    }
799
    handler->endUpdateAll();
800
801
802
803
}

void LldbEngine::requestModuleSymbols(const QString &moduleName)
{
804
805
806
    DebuggerCommand cmd("listSymbols");
    cmd.arg("module", moduleName);
    runCommand(cmd);
807
808
}

809
void LldbEngine::refreshSymbols(const GdbMi &symbols)
810
{
811
    QString moduleName = symbols["module"].toUtf8();
812
813
814
    Symbols syms;
    foreach (const GdbMi &item, symbols["symbols"].children()) {
        Symbol symbol;
815
816
817
818
819
        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();
820
821
        syms.append(symbol);
    }
822
   Internal::showModuleSymbols(moduleName, syms);
823
824
}

825

826
827
828
829
830
831
//////////////////////////////////////////////////////////////////////
//
// Tooltip specific stuff
//
//////////////////////////////////////////////////////////////////////

832
bool LldbEngine::canHandleToolTip(const DebuggerToolTipContext &context) const
833
{
834
   return state() == InferiorStopOk && context.isCppEditor;
835
836
}

837
838
void LldbEngine::updateAll()
{
839
840
841
842
843
844
    DebuggerCommand cmd1("reportThreads");
    runCommand(cmd1);

    DebuggerCommand cmd2("reportCurrentThread");
    runCommand(cmd2);

845
    DebuggerCommand cmd("reportStack");
846
    cmd.arg("nativeMixed", isNativeMixedActive());
847
848
    cmd.arg("stacklimit", action(MaximalStackDepth)->value().toInt());
    cmd.arg("continuation", "updateLocals");
849
850
851
    runCommand(cmd);
}

852
void LldbEngine::reloadFullStack()
853
{
854
    DebuggerCommand cmd("reportStack");
855
    cmd.arg("nativeMixed", isNativeMixedActive());
856
    cmd.arg("stacklimit", -1);
857
858
859
    runCommand(cmd);
}

860
861
862
863
864
865
//////////////////////////////////////////////////////////////////////
//
// Watch specific stuff
//
//////////////////////////////////////////////////////////////////////

866
void LldbEngine::assignValueInDebugger(WatchItem *,
867
    const QString &expression, const QVariant &value)
868
{
869
    DebuggerCommand cmd("assignValue");
870
871
872
    cmd.arg("exp", expression.toLatin1().toHex());
    cmd.arg("value", value.toString().toLatin1().toHex());
    runCommand(cmd);
873
874
}

875
void LldbEngine::doUpdateLocals(const UpdateParameters &params)
876
{
877
878
879
880
881
    if (stackHandler()->stackSize() == 0) {
        showMessage(_("SKIPPING LOCALS DUE TO EMPTY STACK"));
        return;
    }

882
    watchHandler()->notifyUpdateStarted(params.partialVariables());
883

884
    DebuggerCommand cmd("updateData");
885
    cmd.arg("nativeMixed", isNativeMixedActive());
886
    watchHandler()->appendFormatRequests(&cmd);
887
888

    const static bool alwaysVerbose = !qgetenv("QTC_DEBUGGER_PYTHON_VERBOSE").isEmpty();
hjk's avatar
hjk committed
889
    cmd.arg("passexceptions", alwaysVerbose);
hjk's avatar
hjk committed
890
891
892
    cmd.arg("fancy", boolSetting(UseDebuggingHelpers));
    cmd.arg("autoderef", boolSetting(AutoDerefPointers));
    cmd.arg("dyntype", boolSetting(UseDynamicType));
893
    cmd.arg("partialVariable", params.partialVariable);
894
    cmd.arg("sortStructMembers", boolSetting(SortStructMembers));
hjk's avatar
hjk committed
895
896

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

898
    // Watchers
hjk's avatar
hjk committed
899
900
901
    QHashIterator<QByteArray, int> it(WatchHandler::watcherNames());
    while (it.hasNext()) {
        it.next();
902
903
904
905
        cmd.beginGroup();
        cmd.arg("iname", "watch." + QByteArray::number(it.value()));
        cmd.arg("exp", it.key().toHex());
        cmd.endGroup();
906
    }
hjk's avatar
hjk committed
907
908
909
910

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

hjk's avatar
hjk committed
917
918
    cmd.endList();

919
920
    //cmd.arg("resultvarname", m_resultVarName);

921
922
923
    m_lastDebuggableCommand = cmd;
    m_lastDebuggableCommand.args.replace("\"passexceptions\":0", "\"passexceptions\":1");

924
    runCommand(cmd);
925
926

    reloadRegisters();
927
928
929
930
}

void LldbEngine::handleLldbError(QProcess::ProcessError error)
{
931
    showMessage(_("LLDB PROCESS ERROR: %1").arg(error));
932
933
934
935
936
937
938
939
940
941
    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
942
        AsynchronousMessageBox::critical(tr("LLDB I/O Error"), errorMessage(error));
943
944
945
946
947
948
949
950
        break;
    }
}

QString LldbEngine::errorMessage(QProcess::ProcessError error) const
{
    switch (error) {
        case QProcess::FailedToStart:
Leena Miettinen's avatar
Leena Miettinen committed
951
            return tr("The LLDB process failed to start. Either the "
952
                "invoked program \"%1\" is missing, or you may have insufficient "
953
                "permissions to invoke the program.")
954
                .arg(m_lldbCmd);
955
        case QProcess::Crashed:
Leena Miettinen's avatar
Leena Miettinen committed
956
            return tr("The LLDB process crashed some time after starting "
957
958
959
960
961
962
963
                "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
964
                "to the LLDB process. For example, the process may not be running, "
965
966
967
968
969
                "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
970
            return tr("An unknown error in the LLDB process occurred.") + QLatin1Char(' ');
971
972
973
    }
}

974
void LldbEngine::handleLldbFinished(int exitCode, QProcess::ExitStatus exitStatus)
975
{
976
    notifyDebuggerProcessFinished(exitCode, exitStatus, QLatin1String("LLDB"));
977
978
979
980
981
}

void LldbEngine::readLldbStandardError()
{
    QByteArray err = m_lldbProc.readAllStandardError();
982
983
    qDebug() << "\nLLDB STDERR UNEXPECTED: " << err;
    showMessage(_("Lldb stderr: " + err), LogError);
984
985
986
987
988
}

void LldbEngine::readLldbStandardOutput()
{
    QByteArray out = m_lldbProc.readAllStandardOutput();
989
    showMessage(_(out));
990
    m_inbuffer.append(out);
991
    while (true) {
992
        int pos = m_inbuffer.indexOf("@\n");
993
994
995
        if (pos == -1)
            break;
        QByteArray response = m_inbuffer.left(pos).trimmed();
996
        m_inbuffer = m_inbuffer.mid(pos + 2);
997
998
999
1000
        if (response == "lldbstartupok")
            startLldbStage2();
        else
            emit outputReady(response);
1001
1002
1003
    }
}

1004
1005
1006
1007
void LldbEngine::refreshStack(const GdbMi &stack)
{
    StackHandler *handler = stackHandler();
    StackFrames frames;
1008
    foreach (const GdbMi &item, stack["frames"].children()) {
1009
        StackFrame frame;
1010
        frame.level = item["level"].toInt();
1011
1012
1013
        frame.file = item["file"].toUtf8();
        frame.function = item["func"].toUtf8();
        frame.from = item["func"].toUtf8();
1014
        frame.line = item["line"].toInt();
1015
        frame.address = item["addr"].toAddress();
1016
1017
1018
1019
1020
        GdbMi usable = item["usable"];
        if (usable.isValid())
            frame.usable = usable.data().toInt();
        else
            frame.usable = QFileInfo(frame.file).isReadable();
1021
1022
1023