debuggerengine.h 16.5 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
con's avatar
con committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
25

26
#pragma once
27 28 29

#include "debugger_global.h"
#include "debuggerconstants.h"
30
#include "debuggeritem.h"
31
#include "debuggerprotocol.h"
32 33

#include <projectexplorer/devicesupport/idevice.h>
34
#include <projectexplorer/runnables.h>
35
#include <texteditor/textmark.h>
36

37
#include <QObject>
38
#include <QProcess>
39 40 41 42

QT_BEGIN_NAMESPACE
class QDebug;
class QPoint;
43
class QAbstractItemModel;
44 45
QT_END_NAMESPACE

46
namespace Core { class IOptionsPage; }
47

48
namespace Utils { class MacroExpander; }
49 50 51

namespace Debugger {

52
class DebuggerRunTool;
53 54 55 56 57

DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state);

namespace Internal {

58
class DebuggerEnginePrivate;
59
class DebuggerPluginPrivate;
60 61
class DisassemblerAgent;
class MemoryAgent;
62
class WatchItem;
63
class BreakHandler;
64
class LocationMark;
65 66 67 68 69 70 71
class ModulesHandler;
class RegisterHandler;
class StackHandler;
class StackFrame;
class SourceFilesHandler;
class ThreadsHandler;
class WatchHandler;
72
class Breakpoint;
73
class QmlCppEngine;
74
class DebuggerToolTipContext;
hjk's avatar
hjk committed
75
class MemoryViewSetupData;
76
class Terminal;
77
class TerminalRunner;
78
class ThreadId;
79

80
class DebuggerRunParameters
81 82
{
public:
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
    DebuggerStartMode startMode = NoStartMode;
    DebuggerCloseMode closeMode = KillAtClose;

    ProjectExplorer::StandardRunnable inferior;
    QString displayName; // Used in the Snapshots view.
    Utils::ProcessHandle attachPID;
    QStringList solibSearchPath;

    // Used by Qml debugging.
    QUrl qmlServer;

    // Used by general remote debugging.
    QString remoteChannel;
    bool useExtendedRemote = false; // Whether to use GDB's target extended-remote or not.
    QString symbolFile;

    // Used by Mer plugin (3rd party)
    QMap<QString, QString> sourcePathMap;

    // Used by baremetal plugin
    QString commandsForReset; // commands used for resetting the inferior
    bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used
    QString commandsAfterConnect; // additional commands to post after connection to debug target

    // Used by Valgrind
    QStringList expectedSignals;

    // For QNX debugging
    bool useCtrlCStub = false;

    // Used by Android to avoid false positives on warnOnRelease
    bool skipExecutableValidation = false;
    bool useTargetAsync = false;
    QStringList additionalSearchDirectories;

    // Used by iOS.
    QString platform;
    QString deviceSymbolsRoot;
    bool continueAfterAttach = false;
    QString sysRoot;

    // Used by general core file debugging. Public access requested in QTCREATORBUG-17158.
    QString coreFile;

    // Macro-expanded and passed to debugger startup.
    QString additionalStartupCommands;
129

130 131
    DebuggerEngineType cppEngineType = NoEngineType;

132 133
    bool isCppDebugging = true;
    bool isQmlDebugging = false;
134 135 136
    bool breakOnMain = false;
    bool multiProcess = false; // Whether to set detach-on-fork off.

137
    ProjectExplorer::StandardRunnable debugger;
138 139 140 141
    QString overrideStartScript; // Used in attach to core and remote debugging
    QString startMessage; // First status message shown.
    QString debugInfoLocation; // Gdb "set-debug-file-directory".
    QStringList debugSourceLocation; // Gdb "directory"
142
    bool isSnapshot = false; // Set if created internally.
143 144 145 146
    ProjectExplorer::Abi toolChainAbi;

    QString projectSourceDirectory;
    QStringList projectSourceFiles;
147

hjk's avatar
hjk committed
148 149 150 151
    // Used by Script debugging
    QString interpreter;
    QString mainScript;

152 153 154
    // Used by AttachCrashedExternal.
    QString crashParameter;

155 156
    bool nativeMixedEnabled = false;

157 158 159
    bool isNativeMixedDebugging() const;
    void validateExecutable();

160 161
    Utils::MacroExpander *macroExpander = 0;

162
    // For Debugger testing.
163
    int testCase = 0;
164 165

    QStringList validationErrors;
166 167
};

168 169 170
class UpdateParameters
{
public:
171 172
    UpdateParameters(const QString &partialVariable = QString()) :
        partialVariable(partialVariable) {}
173

174
    QStringList partialVariables() const
175
    {
176
        QStringList result;
177 178 179 180 181
        if (!partialVariable.isEmpty())
            result.append(partialVariable);
        return result;
    }

182
    QString partialVariable;
183 184
};

185 186 187
class Location
{
public:
hjk's avatar
hjk committed
188 189 190
    Location() {}
    Location(quint64 address) { m_address = address; }
    Location(const QString &file) { m_fileName = file; }
191
    Location(const QString &file, int line, bool marker = true)
hjk's avatar
hjk committed
192
        { m_lineNumber = line; m_fileName = file; m_needsMarker = marker; }
193
    Location(const StackFrame &frame, bool marker = true);
194 195
    QString fileName() const { return m_fileName; }
    QString functionName() const { return m_functionName; }
196
    QString from() const { return m_from; }
197 198 199 200
    int lineNumber() const { return m_lineNumber; }
    void setNeedsRaise(bool on) { m_needsRaise = on; }
    void setNeedsMarker(bool on) { m_needsMarker = on; }
    void setFileName(const QString &fileName) { m_fileName = fileName; }
201
    void setUseAssembler(bool on) { m_hasDebugInfo = !on; }
202 203 204
    bool needsRaise() const { return m_needsRaise; }
    bool needsMarker() const { return m_needsMarker; }
    bool hasDebugInfo() const { return m_hasDebugInfo; }
205 206
    bool canBeDisassembled() const
        { return m_address != quint64(-1) || !m_functionName.isEmpty(); }
207 208 209
    quint64 address() const { return m_address; }

private:
hjk's avatar
hjk committed
210 211 212 213
    bool m_needsMarker = false;
    bool m_needsRaise = true;
    bool m_hasDebugInfo = true;
    int m_lineNumber = -1;
214 215
    QString m_fileName;
    QString m_functionName;
216
    QString m_from;
hjk's avatar
hjk committed
217
    quint64 m_address = 0;
218 219
};

220 221
enum LocationType { UnknownLocation, LocationByFile, LocationByAddress };

222 223 224
class ContextData
{
public:
225
    bool isValid() const { return type != UnknownLocation; }
226 227

public:
228
    LocationType type = UnknownLocation;
229
    QString fileName;
230 231
    int lineNumber = 0;
    quint64 address = 0;
232 233
};

234
class DebuggerEngine : public QObject
235 236 237 238
{
    Q_OBJECT

public:
239
    explicit DebuggerEngine();
240 241
    virtual ~DebuggerEngine();

242
    const DebuggerRunParameters &runParameters() const;
243

244
    virtual void setRunTool(DebuggerRunTool *runTool);
245
    DebuggerRunTool *runTool() const;
246 247 248

    void start();

249 250 251 252 253 254 255 256 257 258 259 260
    enum {
        // Remove need to qualify each use.
        NeedsTemporaryStop = DebuggerCommand::NeedsTemporaryStop,
        NeedsFullStop = DebuggerCommand::NeedsFullStop,
        Discardable = DebuggerCommand::Discardable,
        ConsoleCommand = DebuggerCommand::ConsoleCommand,
        NeedsFlush = DebuggerCommand::NeedsFlush,
        ExitRequest = DebuggerCommand::ExitRequest,
        RunRequest = DebuggerCommand::RunRequest,
        LosesChild = DebuggerCommand::LosesChild,
        RebuildBreakpointModel = DebuggerCommand::RebuildBreakpointModel,
        InUpdateLocals = DebuggerCommand::InUpdateLocals,
261
        NativeCommand = DebuggerCommand::NativeCommand,
262 263 264
        Silent = DebuggerCommand::Silent
    };

265
    virtual bool canHandleToolTip(const DebuggerToolTipContext &) const;
266 267 268 269
    virtual void expandItem(const QString &iname); // Called when item in tree gets expanded.
    virtual void updateItem(const QString &iname); // Called for fresh watch items.
    void updateWatchData(const QString &iname); // FIXME: Merge with above.
    virtual void selectWatchData(const QString &iname);
270

271
    virtual void prepareForRestart() {}
272

273
    virtual void watchPoint(const QPoint &pnt);
274
    virtual void runCommand(const DebuggerCommand &cmd);
hjk's avatar
hjk committed
275
    virtual void openMemoryView(const MemoryViewSetupData &data);
276 277
    virtual void fetchMemory(MemoryAgent *, quint64 addr, quint64 length);
    virtual void changeMemory(MemoryAgent *, quint64 addr, const QByteArray &data);
278
    virtual void updateMemoryViews();
279
    virtual void openDisassemblerView(const Internal::Location &location);
280
    virtual void fetchDisassembler(Internal::DisassemblerAgent *);
281 282 283 284 285
    virtual void activateFrame(int index);

    virtual void reloadModules();
    virtual void examineModules();
    virtual void loadSymbols(const QString &moduleName);
286
    virtual void loadSymbolsForStack();
287 288
    virtual void loadAllSymbols();
    virtual void requestModuleSymbols(const QString &moduleName);
289
    virtual void requestModuleSections(const QString &moduleName);
290 291 292 293

    virtual void reloadRegisters();
    virtual void reloadSourceFiles();
    virtual void reloadFullStack();
294
    virtual void loadAdditionalQmlStack();
295
    virtual void reloadDebuggingHelpers();
hjk's avatar
hjk committed
296

297
    virtual void setRegisterValue(const QString &name, const QString &value);
298
    virtual void addOptionPages(QList<Core::IOptionsPage*> *) const;
299
    virtual bool hasCapability(unsigned cap) const = 0;
300
    virtual void debugLastCommand() {}
hjk's avatar
hjk committed
301

302
    virtual bool isSynchronous() const;
303 304
    virtual QString qtNamespace() const;
    void setQtNamespace(const QString &ns);
hjk's avatar
hjk committed
305

306 307
    virtual void createSnapshot();
    virtual void updateAll();
308
    virtual void updateLocals();
hjk's avatar
hjk committed
309

310 311
    virtual bool stateAcceptsBreakpointChanges() const { return true; }
    virtual void attemptBreakpointSynchronization();
312 313 314 315
    virtual bool acceptsBreakpoint(Breakpoint bp) const = 0;
    virtual void insertBreakpoint(Breakpoint bp);  // FIXME: make pure
    virtual void removeBreakpoint(Breakpoint bp);  // FIXME: make pure
    virtual void changeBreakpoint(Breakpoint bp);  // FIXME: make pure
hjk's avatar
hjk committed
316

317
    virtual bool acceptsDebuggerCommands() const { return true; }
318 319
    virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);

320
    virtual void assignValueInDebugger(WatchItem *item,
321
        const QString &expr, const QVariant &value);
322
    virtual void selectThread(Internal::ThreadId threadId) = 0;
323

324 325 326 327 328 329 330
    virtual Internal::ModulesHandler *modulesHandler() const;
    virtual Internal::RegisterHandler *registerHandler() const;
    virtual Internal::StackHandler *stackHandler() const;
    virtual Internal::ThreadsHandler *threadsHandler() const;
    virtual Internal::WatchHandler *watchHandler() const;
    virtual Internal::SourceFilesHandler *sourceFilesHandler() const;
    virtual Internal::BreakHandler *breakHandler() const;
331

332 333 334 335
    virtual QAbstractItemModel *modulesModel() const;
    virtual QAbstractItemModel *registerModel() const;
    virtual QAbstractItemModel *stackModel() const;
    virtual QAbstractItemModel *threadsModel() const;
hjk's avatar
hjk committed
336
    virtual QAbstractItemModel *watchModel() const;
337
    virtual QAbstractItemModel *sourceFilesModel() const;
338

339
    void progressPing();
340 341 342 343
    bool debuggerActionsEnabled() const;
    static bool debuggerActionsEnabled(DebuggerState state);

    DebuggerState state() const;
344
    bool isDying() const;
345

346
    static QString stateName(int s);
347

348
    void notifyInferiorPid(const Utils::ProcessHandle &pid);
349 350
    qint64 inferiorPid() const;
    bool isReverseDebugging() const;
351
    void handleCommand(int role, const QVariant &value);
352

353
    // Convenience
354
    Q_SLOT virtual void showMessage(const QString &msg, int channel = LogDebug,
355
        int timeout = -1) const;
356
    Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
357

358
    virtual void resetLocation();
359
    virtual void gotoLocation(const Internal::Location &location);
hjk's avatar
hjk committed
360
    virtual void quitDebugger(); // called when pressing the stop button
361 362

    void abortDebugger(); // called from the debug menu action
363

364
    void updateViews();
hjk's avatar
x  
hjk committed
365
    bool isSlaveEngine() const;
366
    bool isMasterEngine() const;
367
    DebuggerEngine *masterEngine() const;
368
    virtual DebuggerEngine *activeEngine() { return this; }
369
    virtual DebuggerEngine *cppEngine() { return 0; }
370

371
    virtual bool canDisplayTooltip() const;
372

373 374
    virtual void notifyInferiorIll();

375
    QString toFileInProject(const QUrl &fileUrl);
376 377
    void updateBreakpointMarker(const Breakpoint &bp);
    void removeBreakpointMarker(const Breakpoint &bp);
378

379
    QString expand(const QString &string) const;
380
    QString nativeStartupCommands() const;
381

382
protected:
383 384 385
    // The base notify*() function implementation should be sufficient
    // in most cases, but engines are free to override them to do some
    // engine specific cleanup like stopping timers etc.
386 387 388
    void notifyEngineSetupOk();
    void notifyEngineSetupFailed();
    void notifyEngineRunFailed();
389

390 391 392
    void notifyEngineRunAndInferiorRunOk();
    void notifyEngineRunAndInferiorStopOk();
    void notifyEngineRunOkAndInferiorUnrunnable(); // Called by CoreAdapter.
hjk's avatar
hjk committed
393 394

    // Use notifyInferiorRunRequested() plus notifyInferiorRunOk() instead.
395
    // void notifyInferiorSpontaneousRun();
hjk's avatar
hjk committed
396

397 398 399
    void notifyInferiorRunRequested();
    void notifyInferiorRunOk();
    void notifyInferiorRunFailed();
hjk's avatar
hjk committed
400

401 402 403
    void notifyInferiorStopOk();
    void notifyInferiorSpontaneousStop();
    void notifyInferiorStopFailed();
404

405 406 407 408
    public: // FIXME: Remove, currently needed for Android.
    void notifyInferiorExited();

    protected:
409 410
    void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
                                       const QString &backendName);
hjk's avatar
hjk committed
411

412 413
    virtual void setState(DebuggerState state, bool forced = false);

414 415
    void notifyInferiorShutdownOk();
    void notifyInferiorShutdownFailed();
hjk's avatar
hjk committed
416

417
    void notifyEngineSpontaneousShutdown();
418
    void notifyEngineShutdownFinished();
419

420
    void notifyEngineIll();
421

hjk's avatar
hjk committed
422 423 424 425
    virtual void setupEngine() = 0;
    virtual void runEngine() = 0;
    virtual void shutdownInferior() = 0;
    virtual void shutdownEngine() = 0;
426
    virtual void resetInferior() {}
hjk's avatar
hjk committed
427

428 429
    virtual void detachDebugger();
    virtual void executeStep();
430
    virtual void executeStepOut();
431 432 433 434 435 436 437
    virtual void executeNext();
    virtual void executeStepI();
    virtual void executeNextI();
    virtual void executeReturn();

    virtual void continueInferior();
    virtual void interruptInferior();
438
    void requestInterruptInferior();
439

440
    virtual void executeRunToLine(const Internal::ContextData &data);
441
    virtual void executeRunToFunction(const QString &functionName);
442
    virtual void executeJumpToLine(const Internal::ContextData &data);
443 444 445 446

    virtual void frameUp();
    virtual void frameDown();

447 448
    virtual void abortDebuggerProcess() {} // second attempt

449 450
    virtual void doUpdateLocals(const UpdateParameters &params);

451
    void setMasterEngine(DebuggerEngine *masterEngine);
452

453
    TerminalRunner *terminal() const;
hjk's avatar
hjk committed
454

455 456
    static QString msgStopped(const QString &reason = QString());
    static QString msgStoppedBySignal(const QString &meaning, const QString &name);
hjk's avatar
hjk committed
457 458
    static QString msgStoppedByException(const QString &description,
        const QString &threadId);
459
    static QString msgInterrupted();
460
    bool showStoppedBySignalMessageBox(const QString meaning, QString name);
461 462
    void showStoppedByExceptionMessageBox(const QString &description);

463 464 465 466
    virtual void setupSlaveEngine();
    virtual void runSlaveEngine();
    virtual void shutdownSlaveEngine();

467 468 469
    virtual void slaveEngineStateChanged(DebuggerEngine *engine,
        DebuggerState state);

470
    void updateLocalsView(const GdbMi &all);
471
    void checkState(DebuggerState state, const char *file, int line);
472 473 474
    bool isNativeMixedEnabled() const;
    bool isNativeMixedActive() const;
    bool isNativeMixedActiveFrame() const;
475

hjk's avatar
hjk committed
476
private:
477
    // Wrapper engine needs access to state of its subengines.
478 479
    friend class QmlCppEngine;
    friend class DebuggerPluginPrivate;
480

hjk's avatar
hjk committed
481
    friend class DebuggerEnginePrivate;
482
    friend class LocationMark;
483 484 485
    DebuggerEnginePrivate *d;
};

486 487 488 489
class LocationMark : public TextEditor::TextMark
{
public:
    LocationMark(DebuggerEngine *engine, const QString &file, int line);
490
    void removedFromEditor() override { updateLineNumber(0); }
491 492

private:
493 494
    bool isDraggable() const override;
    void dragToLine(int line) override;
495 496 497 498

    QPointer<DebuggerEngine> m_engine;
};

499
} // namespace Internal
500 501
} // namespace Debugger

502
Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters)
503
Q_DECLARE_METATYPE(Debugger::Internal::ContextData)