Debugger: Rework GDB disassembly display
[qt-creator:qt-creator.git] / src / plugins / debugger / gdb / gdbengine.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and Digia.  For licensing terms and
13 ** conditions see http://qt.digia.com/licensing.  For further information
14 ** use the contact form at http://qt.digia.com/contact-us.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Digia gives you certain additional
25 ** rights.  These rights are described in the Digia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ****************************************************************************/
29
30 #ifndef DEBUGGER_GDBENGINE_H
31 #define DEBUGGER_GDBENGINE_H
32
33 #include <debugger/debuggerengine.h>
34
35 #include <debugger/watchhandler.h>
36 #include <debugger/watchutils.h>
37
38 #include <coreplugin/id.h>
39
40 #include <projectexplorer/devicesupport/idevice.h>
41
42 #include <QProcess>
43 #include <QTextCodec>
44 #include <QTime>
45 #include <QTimer>
46
47 namespace Debugger {
48 namespace Internal {
49
50 class GdbProcess;
51 class DebugInfoTask;
52 class DebugInfoTaskHandler;
53 class GdbResponse;
54 class GdbMi;
55 class MemoryAgentCookie;
56
57 class WatchData;
58 class DisassemblerAgentCookie;
59 class DisassemblerLines;
60
61 class GdbEngine : public Debugger::DebuggerEngine
62 {
63     Q_OBJECT
64
65 public:
66     explicit GdbEngine(const DebuggerStartParameters &startParameters);
67     ~GdbEngine();
68
69 private: ////////// General Interface //////////
70
71     virtual void setupEngine() = 0;
72     virtual void handleGdbStartFailed();
73     virtual void setupInferior() = 0;
74     virtual void notifyInferiorSetupFailed();
75
76     virtual bool hasCapability(unsigned) const;
77     virtual void detachDebugger();
78     virtual void shutdownInferior();
79     virtual void shutdownEngine() = 0;
80     virtual void abortDebugger();
81
82     virtual bool acceptsDebuggerCommands() const;
83     virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages);
84     virtual QByteArray qtNamespace() const { return m_qtNamespace; }
85     virtual void setQtNamespace(const QByteArray &ns) { m_qtNamespace = ns; }
86
87 private: ////////// General State //////////
88
89     DebuggerStartMode startMode() const;
90     Q_SLOT void reloadLocals();
91
92     bool m_registerNamesListed;
93
94 protected: ////////// Gdb Process Management //////////
95
96     void startGdb(const QStringList &args = QStringList());
97     void handleInferiorShutdown(const GdbResponse &response);
98     void handleGdbExit(const GdbResponse &response);
99
100     void loadInitScript();
101
102     // Something went wrong with the adapter *before* adapterStarted() was emitted.
103     // Make sure to clean up everything before emitting this signal.
104     void handleAdapterStartFailed(const QString &msg,
105         Core::Id settingsIdHint = Core::Id());
106
107     // This triggers the initial breakpoint synchronization and causes
108     // finishInferiorSetup() being called once done.
109     void handleInferiorPrepared();
110     // This notifies the base of a successful inferior setup.
111     void finishInferiorSetup();
112
113     void handleDebugInfoLocation(const GdbResponse &response);
114
115     // The adapter is still running just fine, but it failed to acquire a debuggee.
116     void notifyInferiorSetupFailed(const QString &msg);
117
118     void notifyAdapterShutdownOk();
119     void notifyAdapterShutdownFailed();
120
121     // Something went wrong with the adapter *after* adapterStarted() was emitted.
122     // Make sure to clean up everything before emitting this signal.
123     void handleAdapterCrashed(const QString &msg);
124
125 private slots:
126     void handleInterruptDeviceInferior(const QString &error);
127     void handleGdbFinished(int, QProcess::ExitStatus status);
128     void handleGdbError(QProcess::ProcessError error);
129     void readGdbStandardOutput();
130     void readGdbStandardError();
131     void readDebugeeOutput(const QByteArray &data);
132
133 private:
134     QTextCodec *m_outputCodec;
135     QTextCodec::ConverterState m_outputCodecState;
136
137     QByteArray m_inbuffer;
138     bool m_busy;
139
140     // Name of the convenience variable containing the last
141     // known function return value.
142     QByteArray m_resultVarName;
143
144 private: ////////// Gdb Command Management //////////
145
146     public: // Otherwise the Qt flag macros are unhappy.
147     enum GdbCommandFlag {
148         NoFlags = 0,
149         // The command needs a stopped inferior.
150         NeedsStop = 1,
151         // No need to wait for the reply before continuing inferior.
152         Discardable = 2,
153         // We can live without receiving an answer.
154         NonCriticalResponse = 8,
155         // Callback expects GdbResultRunning instead of GdbResultDone.
156         RunRequest = 16,
157         // Callback expects GdbResultExit instead of GdbResultDone.
158         ExitRequest = 32,
159         // Auto-set inferior shutdown related states.
160         LosesChild = 64,
161         // Trigger breakpoint model rebuild when no such commands are pending anymore.
162         RebuildBreakpointModel = 128,
163         // This command needs to be send immediately.
164         Immediate = 256,
165         // This is a command that needs to be wrapped into -interpreter-exec console
166         ConsoleCommand = 512
167     };
168     Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
169
170     protected:
171     typedef void (GdbEngine::*GdbCommandCallback)(const GdbResponse &response);
172
173     struct GdbCommand
174     {
175         GdbCommand()
176             : flags(0), callback(0), callbackName(0)
177         {}
178
179         int flags;
180         GdbCommandCallback callback;
181         const char *callbackName;
182         QByteArray command;
183         QVariant cookie;
184         QTime postTime;
185     };
186
187     // Type and cookie are sender-internal data, opaque for the "event
188     // queue". resultNeeded == true increments m_pendingResults on
189     // send and decrements on receipt, effectively preventing
190     // watch model updates before everything is finished.
191     void flushCommand(const GdbCommand &cmd);
192 protected:
193     void postCommand(const QByteArray &command,
194                      GdbCommandFlags flags,
195                      GdbCommandCallback callback = 0,
196                      const char *callbackName = 0,
197                      const QVariant &cookie = QVariant());
198     void postCommand(const QByteArray &command,
199                      GdbCommandCallback callback = 0,
200                      const char *callbackName = 0,
201                      const QVariant &cookie = QVariant());
202 private:
203     void postCommandHelper(const GdbCommand &cmd);
204     void flushQueuedCommands();
205     Q_SLOT void commandTimeout();
206     void setTokenBarrier();
207
208     // Sets up an "unexpected result" for the following commeand.
209     void scheduleTestResponse(int testCase, const QByteArray &response);
210
211     QHash<int, GdbCommand> m_cookieForToken;
212     int commandTimeoutTime() const;
213     QTimer m_commandTimer;
214
215     QByteArray m_pendingConsoleStreamOutput;
216     QByteArray m_pendingLogStreamOutput;
217
218     // This contains the first token number for the current round
219     // of evaluation. Responses with older tokens are considers
220     // out of date and discarded.
221     int m_oldestAcceptableToken;
222     int m_nonDiscardableCount;
223
224     int m_pendingBreakpointRequests; // Watch updating commands in flight
225
226     typedef void (GdbEngine::*CommandsDoneCallback)();
227     // This function is called after all previous responses have been received.
228     CommandsDoneCallback m_commandsDoneCallback;
229
230     QList<GdbCommand> m_commandsToRunOnTemporaryBreak;
231
232 private: ////////// Gdb Output, State & Capability Handling //////////
233 protected:
234     Q_SLOT void handleResponse(const QByteArray &buff);
235     void handleStopResponse(const GdbMi &data);
236     void handleResultRecord(GdbResponse *response);
237     void handleStop1(const GdbResponse &response);
238     void handleStop1(const GdbMi &data);
239     void handleStop2(const GdbResponse &response);
240     void handleStop2(const GdbMi &data);
241     Q_SLOT void handleStop2();
242     StackFrame parseStackFrame(const GdbMi &mi, int level);
243     void resetCommandQueue();
244
245     bool isSynchronous() const { return true; }
246
247     // Gdb initialization sequence
248     void handleShowVersion(const GdbResponse &response);
249     void handleListFeatures(const GdbResponse &response);
250     void handlePythonSetup(const GdbResponse &response);
251
252     int m_gdbVersion; // 7.6.1 is 70601
253     bool m_isQnxGdb;
254
255 private: ////////// Inferior Management //////////
256
257     // This should be always the last call in a function.
258     bool stateAcceptsBreakpointChanges() const;
259     bool acceptsBreakpoint(BreakpointModelId id) const;
260     void insertBreakpoint(BreakpointModelId id);
261     void removeBreakpoint(BreakpointModelId id);
262     void changeBreakpoint(BreakpointModelId id);
263
264     void executeStep();
265     void executeStepOut();
266     void executeNext();
267     void executeStepI();
268     void executeNextI();
269
270     protected:
271     void continueInferiorInternal();
272     void autoContinueInferior();
273     void continueInferior();
274     void interruptInferior();
275     virtual void interruptInferior2() {}
276     void interruptInferiorTemporarily();
277
278     void executeRunToLine(const ContextData &data);
279     void executeRunToFunction(const QString &functionName);
280     void executeJumpToLine(const ContextData &data);
281     void executeReturn();
282
283     void handleExecuteContinue(const GdbResponse &response);
284     void handleExecuteStep(const GdbResponse &response);
285     void handleExecuteNext(const GdbResponse &response);
286     void handleExecuteReturn(const GdbResponse &response);
287     void handleExecuteJumpToLine(const GdbResponse &response);
288     void handleExecuteRunToLine(const GdbResponse &response);
289
290     void maybeHandleInferiorPidChanged(const QString &pid);
291     void handleInfoProc(const GdbResponse &response);
292     QString msgPtraceError(DebuggerStartMode sm);
293
294 private: ////////// View & Data Stuff //////////
295
296     void selectThread(ThreadId threadId);
297     void activateFrame(int index);
298     void resetLocation();
299
300     //
301     // Breakpoint specific stuff
302     //
303     void handleBreakModifications(const GdbMi &bkpts);
304     void handleBreakIgnore(const GdbResponse &response);
305     void handleBreakDisable(const GdbResponse &response);
306     void handleBreakEnable(const GdbResponse &response);
307     void handleBreakInsert1(const GdbResponse &response);
308     void handleBreakInsert2(const GdbResponse &response);
309     void handleTraceInsert2(const GdbResponse &response);
310     void handleBreakCondition(const GdbResponse &response);
311     void handleBreakThreadSpec(const GdbResponse &response);
312     void handleBreakLineNumber(const GdbResponse &response);
313     void handleWatchInsert(const GdbResponse &response);
314     void handleCatchInsert(const GdbResponse &response);
315     void handleBkpt(const GdbMi &bkpt, const BreakpointModelId &id);
316     void updateResponse(BreakpointResponse &response, const GdbMi &bkpt);
317     QByteArray breakpointLocation(BreakpointModelId id); // For gdb/MI.
318     QByteArray breakpointLocation2(BreakpointModelId id); // For gdb/CLI fallback.
319     QString breakLocation(const QString &file) const;
320
321     //
322     // Modules specific stuff
323     //
324     protected:
325     void loadSymbols(const QString &moduleName);
326     Q_SLOT void loadAllSymbols();
327     void loadSymbolsForStack();
328     void requestModuleSymbols(const QString &moduleName);
329     void requestModuleSections(const QString &moduleName);
330     void reloadModules();
331     void examineModules();
332
333     void reloadModulesInternal();
334     void handleModulesList(const GdbResponse &response);
335     void handleShowModuleSymbols(const GdbResponse &response);
336     void handleShowModuleSections(const GdbResponse &response);
337
338     //
339     // Snapshot specific stuff
340     //
341     virtual void createSnapshot();
342     void handleMakeSnapshot(const GdbResponse &response);
343
344     //
345     // Register specific stuff
346     //
347     Q_SLOT void reloadRegisters();
348     void setRegisterValue(int nr, const QString &value);
349     void handleRegisterListNames(const GdbResponse &response);
350     void handleRegisterListValues(const GdbResponse &response);
351     QVector<int> m_registerNumbers; // Map GDB register numbers to indices
352
353     //
354     // Disassembler specific stuff
355     //
356     // Chain of fallbacks: PointMixed -> PointPlain -> RangeMixed -> RangePlain.
357     void fetchDisassembler(DisassemblerAgent *agent);
358     void fetchDisassemblerByCliPointMixed(const DisassemblerAgentCookie &ac);
359     void fetchDisassemblerByCliRangeMixed(const DisassemblerAgentCookie &ac);
360     void fetchDisassemblerByCliRangePlain(const DisassemblerAgentCookie &ac);
361     void handleFetchDisassemblerByCliPointMixed(const GdbResponse &response);
362     void handleFetchDisassemblerByCliRangeMixed(const GdbResponse &response);
363     void handleFetchDisassemblerByCliRangePlain(const GdbResponse &response);
364     bool handleCliDisassemblerResult(const QByteArray &response, DisassemblerAgent *agent);
365     Q_SLOT void reloadDisassembly();
366
367     void handleBreakOnQFatal(const GdbResponse &response);
368
369     //
370     // Source file specific stuff
371     //
372     void reloadSourceFiles();
373     void reloadSourceFilesInternal();
374     void handleQuerySources(const GdbResponse &response);
375
376     QString fullName(const QString &fileName);
377     QString cleanupFullName(const QString &fileName);
378
379     // awful hack to keep track of used files
380     QMap<QString, QString> m_shortToFullName;
381     QMap<QString, QString> m_fullToShortName;
382     QMultiMap<QString, QString> m_baseNameToFullName;
383
384     bool m_sourcesListUpdating;
385
386     //
387     // Stack specific stuff
388     //
389 protected:
390     void updateAll();
391     void handleStackListFrames(const GdbResponse &response);
392     void handleStackSelectThread(const GdbResponse &response);
393     void handleStackSelectFrame(const GdbResponse &response);
394     void handleThreadListIds(const GdbResponse &response);
395     void handleThreadInfo(const GdbResponse &response);
396     void handleThreadNames(const GdbResponse &response);
397     Q_SLOT void reloadStack(bool forceGotoLocation);
398     Q_SLOT virtual void reloadFullStack();
399     virtual void loadAdditionalQmlStack();
400     void handleQmlStackFrameArguments(const GdbResponse &response);
401     void handleQmlStackTrace(const GdbResponse &response);
402     int currentFrame() const;
403
404     QList<GdbMi> m_currentFunctionArgs;
405
406     //
407     // Watch specific stuff
408     //
409     virtual bool setToolTipExpression(const QPoint &mousePos,
410         TextEditor::ITextEditor *editor, const DebuggerToolTipContext &);
411     virtual void assignValueInDebugger(const WatchData *data,
412         const QString &expr, const QVariant &value);
413
414     virtual void fetchMemory(MemoryAgent *agent, QObject *token,
415         quint64 addr, quint64 length);
416     void fetchMemoryHelper(const MemoryAgentCookie &cookie);
417     void handleChangeMemory(const GdbResponse &response);
418     virtual void changeMemory(MemoryAgent *agent, QObject *token,
419         quint64 addr, const QByteArray &data);
420     void handleFetchMemory(const GdbResponse &response);
421
422     virtual void watchPoint(const QPoint &);
423     void handleWatchPoint(const GdbResponse &response);
424
425     void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags);
426     void rebuildWatchModel();
427     void showToolTip();
428
429     void insertData(const WatchData &data);
430
431     void handleVarAssign(const GdbResponse &response);
432     void handleDetach(const GdbResponse &response);
433     void handleThreadGroupCreated(const GdbMi &result);
434     void handleThreadGroupExited(const GdbMi &result);
435
436     Q_SLOT void createFullBacktrace();
437     void handleCreateFullBacktrace(const GdbResponse &response);
438
439     void updateLocals();
440         void updateLocalsPython(const UpdateParameters &parameters);
441             void handleStackFramePython(const GdbResponse &response);
442
443     void setLocals(const QList<GdbMi> &locals);
444
445     QSet<QByteArray> m_processedNames;
446     struct TypeInfo
447     {
448         TypeInfo(uint s = 0) : size(s) {}
449
450         uint size;
451     };
452
453     QHash<QByteArray, TypeInfo> m_typeInfoCache;
454
455     //
456     // Dumper Management
457     //
458     void reloadDebuggingHelpers();
459
460     QByteArray m_qtNamespace;
461     QString m_gdb;
462
463     //
464     // Convenience Functions
465     //
466     QString errorMessage(QProcess::ProcessError error);
467     void showExecutionError(const QString &message);
468
469     static QByteArray tooltipIName(const QString &exp);
470     QString tooltipExpression() const;
471     QScopedPointer<DebuggerToolTipContext> m_toolTipContext;
472
473     // For short-circuiting stack and thread list evaluation.
474     bool m_stackNeeded;
475
476     //
477     // Qml
478     //
479     BreakpointResponseId m_qmlBreakpointResponseId1;
480     BreakpointResponseId m_qmlBreakpointResponseId2;
481     bool m_preparedForQmlBreak;
482     bool setupQmlStep(bool on);
483     void handleSetQmlStepBreakpoint(const GdbResponse &response);
484     bool isQmlStepBreakpoint(const BreakpointResponseId &id) const;
485     bool isQmlStepBreakpoint1(const BreakpointResponseId &id) const;
486     bool isQmlStepBreakpoint2(const BreakpointResponseId &id) const;
487     bool isQFatalBreakpoint(const BreakpointResponseId &id) const;
488     bool isHiddenBreakpoint(const BreakpointResponseId &id) const;
489
490     // HACK:
491     QByteArray m_currentThread;
492     QString m_lastWinException;
493     QString m_lastMissingDebugInfo;
494     BreakpointResponseId m_qFatalBreakpointResponseId;
495     bool m_terminalTrap;
496
497     bool usesExecInterrupt() const;
498
499     QHash<int, QByteArray> m_scheduledTestResponses;
500     QSet<int> m_testCases;
501
502     // Debug information
503     friend class DebugInfoTaskHandler;
504     void requestDebugInformation(const DebugInfoTask &task);
505     DebugInfoTaskHandler *m_debugInfoTaskHandler;
506
507     // Indicates whether we had at least one full attempt to load
508     // debug information.
509     bool attemptQuickStart() const;
510     bool m_fullStartDone;
511     bool m_systemDumpersLoaded;
512
513     // Test
514     QList<WatchData> m_completed;
515     QSet<QByteArray> m_uncompleted;
516
517     static QString msgGdbStopFailed(const QString &why);
518     static QString msgInferiorStopFailed(const QString &why);
519     static QString msgAttachedToStoppedInferior();
520     static QString msgInferiorSetupOk();
521     static QString msgInferiorRunOk();
522     static QString msgConnectRemoteServerFailed(const QString &why);
523     static QByteArray dotEscape(QByteArray str);
524
525     void debugLastCommand();
526     QByteArray m_lastDebuggableCommand;
527
528 protected:
529     virtual void write(const QByteArray &data);
530
531 protected:
532     bool prepareCommand();
533     void interruptLocalInferior(qint64 pid);
534
535     GdbProcess *m_gdbProc;
536     ProjectExplorer::DeviceProcessSignalOperation::Ptr m_signalOperation;
537 };
538
539 } // namespace Internal
540 } // namespace Debugger
541
542 Q_DECLARE_OPERATORS_FOR_FLAGS(Debugger::Internal::GdbEngine::GdbCommandFlags)
543
544 #endif // DEBUGGER_GDBENGINE_H