cdbengine.h 12.7 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** 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
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29
30
31
32

#ifndef DEBUGGER_CDBENGINE_H
#define DEBUGGER_CDBENGINE_H

33
#include <debugger/debuggerengine.h>
34

35
36
#include <projectexplorer/devicesupport/idevice.h>

37
38
39
#include <QSharedPointer>
#include <QProcess>
#include <QMap>
40
#include <QVariant>
41
#include <QTime>
42

43
namespace Utils { class ConsoleProcess; }
44
namespace Debugger {
45
namespace Internal {
46

47
class DisassemblerAgent;
48
49
struct CdbBuiltinCommand;
struct CdbExtensionCommand;
50
struct MemoryViewCookie;
51
class ByteArrayInputStream;
52
class GdbMi;
53
54
55
56
57
58
59
60
61
62
63
64

class CdbEngine : public Debugger::DebuggerEngine
{
    Q_OBJECT

public:
    enum CommandFlags { QuietCommand = 0x1 };
    // Flag bits for a sequence of commands
    enum CommandSequenceFlags {
        CommandListStack = 0x1,
        CommandListThreads = 0x2,
        CommandListRegisters = 0x4,
65
66
        CommandListModules = 0x8,
        CommandListBreakPoints = 0x10
67
68
69
70
71
72
73
    };

    typedef QSharedPointer<CdbBuiltinCommand> CdbBuiltinCommandPtr;
    typedef QSharedPointer<CdbExtensionCommand> CdbExtensionCommandPtr;
    typedef void (CdbEngine::*BuiltinCommandHandler)(const CdbBuiltinCommandPtr &);
    typedef void (CdbEngine::*ExtensionCommandHandler)(const CdbExtensionCommandPtr &);

74
    CdbEngine(const DebuggerStartParameters &sp);
75
    ~CdbEngine();
76

77
78
    // Factory function that returns 0 if the debug engine library cannot be found.

79
    virtual bool setToolTipExpression(TextEditor::BaseTextEditor *editor,
80
                                      const DebuggerToolTipContext &ctx);
81
82
83
84
85
86
    virtual void setupEngine();
    virtual void setupInferior();
    virtual void runEngine();
    virtual void shutdownInferior();
    virtual void shutdownEngine();
    virtual void detachDebugger();
87
88
    virtual void updateWatchData(const WatchData &data,
                                 const WatchUpdateFlags & flags = WatchUpdateFlags());
hjk's avatar
hjk committed
89
    virtual bool hasCapability(unsigned cap) const;
90
    virtual void watchPoint(const QPoint &);
91
92
93
94
95
96
97
98
99
100
101
    virtual void setRegisterValue(int regnr, const QString &value);

    virtual void executeStep();
    virtual void executeStepOut();
    virtual void executeNext();
    virtual void executeStepI();
    virtual void executeNextI();

    virtual void continueInferior();
    virtual void interruptInferior();

102
    virtual void executeRunToLine(const ContextData &data);
103
    virtual void executeRunToFunction(const QString &functionName);
104
    virtual void executeJumpToLine(const ContextData &data);
105
    virtual void assignValueInDebugger(const WatchData *w, const QString &expr, const QVariant &value);
106
    virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
107
108

    virtual void activateFrame(int index);
hjk's avatar
hjk committed
109
    virtual void selectThread(ThreadId threadId);
110

111
    virtual bool stateAcceptsBreakpointChanges() const;
112
    virtual bool acceptsBreakpoint(BreakpointModelId id) const;
113
114
    virtual void attemptBreakpointSynchronization();

115
116
    virtual void fetchDisassembler(DisassemblerAgent *agent);
    virtual void fetchMemory(MemoryAgent *, QObject *, quint64 addr, quint64 length);
117
    virtual void changeMemory(Internal::MemoryAgent *, QObject *, quint64 addr, const QByteArray &data);
118
119
120
121
122
123
124
125
126

    virtual void reloadModules();
    virtual void loadSymbols(const QString &moduleName);
    virtual void loadAllSymbols();
    virtual void requestModuleSymbols(const QString &moduleName);

    virtual void reloadRegisters();
    virtual void reloadSourceFiles();
    virtual void reloadFullStack();
127
    void loadAdditionalQmlStack();
128

129
    static QString extensionLibraryName(bool is64Bit);
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

private slots:
    void readyReadStandardOut();
    void readyReadStandardError();
    void processError();
    void processFinished();
    void postCommand(const QByteArray &cmd, unsigned flags);
    void postBuiltinCommand(const QByteArray &cmd,
                            unsigned flags,
                            BuiltinCommandHandler handler,
                            unsigned nextCommandFlag = 0,
                            const QVariant &cookie = QVariant());

    void postExtensionCommand(const QByteArray &cmd,
                              const QByteArray &arguments,
                              unsigned flags,
                              ExtensionCommandHandler handler,
                              unsigned nextCommandFlag = 0,
                              const QVariant &cookie = QVariant());

    void postCommandSequence(unsigned mask);
    void operateByInstructionTriggered(bool);
152
    void verboseLogTriggered(bool);
153

154
    void consoleStubError(const QString &);
155
156
157
    void consoleStubProcessStarted();
    void consoleStubExited();

158
159
    void createFullBacktrace();

160
161
    void handleDoInterruptInferior(const QString &errorMessage);

162
private:
163
    typedef QHash<BreakpointModelId, BreakpointResponse> PendingBreakPointMap;
164
165
166
167
168
169
170
171
    typedef QPair<QString, QString> SourcePathMapping;
    struct NormalizedSourceFileName // Struct for caching mapped/normalized source files.
    {
        NormalizedSourceFileName(const QString &fn = QString(), bool e = false) : fileName(fn), exists(e) {}

        QString fileName;
        bool exists;
    };
172

173
174
175
176
    enum SpecialStopMode
    {
        NoSpecialStop,
        SpecialStopSynchronizeBreakpoints,
177
178
        SpecialStopGetWidgetAt,
        CustomSpecialStop // Associated with m_specialStopData, handleCustomSpecialStop()
179
    };
180
181
    enum ParseStackResultFlags // Flags returned by parseStackTrace
    {
182
        ParseStackStepInto = 1, // Need to execute a step, hit on a call frame in "Step into"
183
184
        ParseStackStepOut = 2, // Need to step out, hit on a frame without debug information
        ParseStackWow64 = 3 // Hit on a frame with 32bit emulation, switch debugger to 32 bit mode
185
186
    };

187

188
    bool startConsole(const DebuggerStartParameters &sp, QString *errorMessage);
189
    void init();
190
    unsigned examineStopReason(const GdbMi &stopReason, QString *message,
191
192
193
                               QString *exceptionBoxMessage,
                               bool conditionalBreakPointTriggered = false);
    void processStop(const GdbMi &stopReason, bool conditionalBreakPointTriggered = false);
194
    bool commandsPending() const;
195
196
    void handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message);
    bool doSetupEngine(QString *errorMessage);
197
    bool launchCDB(const DebuggerStartParameters &sp, QString *errorMessage);
198
199
200
    void handleSessionAccessible(unsigned long cdbExState);
    void handleSessionInaccessible(unsigned long cdbExState);
    void handleSessionIdle(const QByteArray &message);
201
    void doInterruptInferior(SpecialStopMode sm);
202
    void doInterruptInferiorCustomSpecialStop(const QVariant &v);
203
204
205
    void doContinueInferior();
    inline void parseOutputLine(QByteArray line);
    inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
206
    bool canInterruptInferior() const;
207
    void syncOperateByInstruction(bool operateByInstruction);
208
    void syncVerboseLog(bool verboseLog);
209
    void postWidgetAtCommand();
210
    void handleCustomSpecialStop(const QVariant &v);
211
    void postFetchMemory(const MemoryViewCookie &c);
212
213
214
215
216
    inline void postDisassemblerCommand(quint64 address, const QVariant &cookie = QVariant());
    void postDisassemblerCommand(quint64 address, quint64 endAddress,
                                 const QVariant &cookie = QVariant());
    void postResolveSymbol(const QString &module, const QString &function,
                           const QVariant &cookie =  QVariant());
217
    void evaluateExpression(QByteArray exp, const QVariant &cookie = QVariant());
218
219
    // Builtin commands
    void dummyHandler(const CdbBuiltinCommandPtr &);
220
    void handleStackTrace(const CdbExtensionCommandPtr &);
221
222
223
    void handleRegisters(const CdbBuiltinCommandPtr &);
    void handleDisassembler(const CdbBuiltinCommandPtr &);
    void handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &);
224
    void handleExpression(const CdbExtensionCommandPtr &);
225
226
    void handleResolveSymbol(const CdbBuiltinCommandPtr &command);
    void handleResolveSymbol(const QList<quint64> &addresses, const QVariant &cookie);
227
    void handleBreakInsert(const CdbBuiltinCommandPtr &cmd);
228
229
230
    void handleCheckWow64(const CdbBuiltinCommandPtr &cmd);
    void ensureUsing32BitStackInWow64(const CdbBuiltinCommandPtr &cmd);
    void handleSwitchWow64Stack(const CdbBuiltinCommandPtr &cmd);
231
    void jumpToAddress(quint64 address);
232
    void handleCreateFullBackTrace(const CdbBuiltinCommandPtr &cmd);
233

234
235
236
237
    // Extension commands
    void handleThreads(const CdbExtensionCommandPtr &);
    void handlePid(const CdbExtensionCommandPtr &reply);
    void handleLocals(const CdbExtensionCommandPtr &reply);
238
    void handleAddWatch(const CdbExtensionCommandPtr &reply);
239
240
241
242
    void handleExpandLocals(const CdbExtensionCommandPtr &reply);
    void handleRegisters(const CdbExtensionCommandPtr &reply);
    void handleModules(const CdbExtensionCommandPtr &reply);
    void handleMemory(const CdbExtensionCommandPtr &);
243
    void handleWidgetAt(const CdbExtensionCommandPtr &);
244
245
    void handleBreakPoints(const CdbExtensionCommandPtr &);
    void handleBreakPoints(const GdbMi &value);
246
    void handleAdditionalQmlStack(const CdbExtensionCommandPtr &);
247
    NormalizedSourceFileName sourceMapNormalizeFileNameFromDebugger(const QString &f);
248
    void updateLocalVariable(const QByteArray &iname);
249
    void updateLocals(bool forNewStackFrame = false);
250
    int elapsedLogTime() const;
251
    void addLocalsOptions(ByteArrayInputStream &s) const;
252
    unsigned parseStackTrace(const GdbMi &data, bool sourceStepInto);
253
    void mergeStartParametersSourcePathMap();
254
255
256
257

    const QByteArray m_tokenPrefix;

    QProcess m_process;
258
259
    QScopedPointer<Utils::ConsoleProcess> m_consoleStub;
    DebuggerStartMode m_effectiveStartMode;
260
    QByteArray m_outputBuffer;
261
    //! Debugger accessible (expecting commands)
262
263
    bool m_accessible;
    SpecialStopMode m_specialStopMode;
264
    ProjectExplorer::DeviceProcessSignalOperation::Ptr m_signalOperation;
265
266
    int m_nextCommandToken;
    QList<CdbBuiltinCommandPtr> m_builtinCommandQueue;
267
    int m_currentBuiltinCommandIndex; //!< Current command whose output is recorded.
268
    QList<CdbExtensionCommandPtr> m_extensionCommandQueue;
269
    QMap<QString, NormalizedSourceFileName> m_normalizedFileCache;
270
271
    const QByteArray m_extensionCommandPrefixBA; //!< Library name used as prefix
    bool m_operateByInstructionPending; //!< Creator operate by instruction action changed.
272
    bool m_operateByInstruction;
273
274
    bool m_verboseLogPending; //!< Creator verbose log action changed.
    bool m_verboseLog;
275
276
    bool m_notifyEngineShutdownOnTermination;
    bool m_hasDebuggee;
277
278
279
280
281
282
    enum Wow64State {
        wow64Uninitialized,
        noWow64Stack,
        wow64Stack32Bit,
        wow64Stack64Bit
    } m_wow64State;
283
284
    QTime m_logTime;
    mutable int m_elapsedLogTime;
285
    QByteArray m_extensionMessageBuffer;
286
    bool m_sourceStepInto;
287
288
    int m_watchPointX;
    int m_watchPointY;
289
    PendingBreakPointMap m_pendingBreakpointMap;
290
291
    PendingBreakPointMap m_insertSubBreakpointMap;
    PendingBreakPointMap m_pendingSubBreakpointMap;
292
    bool m_autoBreakPointCorrection;
293
    QHash<QString, QString> m_fileNameModuleHash;
294
    QMultiHash<QString, quint64> m_symbolAddressCache;
295
    QHash<QByteArray, QString> m_watchInameToName;
296
    bool m_ignoreCdbOutput;
297
    QVariantList m_customSpecialStopData;
298
    QList<SourcePathMapping> m_sourcePathMappings;
299
    QScopedPointer<GdbMi> m_coreStopReason;
300
301
};

302
} // namespace Internal
303
304
305
} // namespace Debugger

#endif // DEBUGGER_CDBENGINE_H