1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 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 The Qt Company. For licensing terms 13 ** and conditions see https://www.qt.io/terms-conditions. For further 14 ** information use the contact form at https://www.qt.io/contact-us. 15 ** 16 ** GNU General Public License Usage 17 ** Alternatively, this file may be used under the terms of the GNU 18 ** General Public License version 3 as published by the Free Software 19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 20 ** included in the packaging of this file. Please review the following 21 ** information to ensure the GNU General Public License requirements will 22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 23 ** 24 ****************************************************************************/ 25 26 #pragma once 27 28 #include "debugger_global.h" 29 #include "debuggerconstants.h" 30 #include "debuggeritem.h" 31 #include "debuggerprotocol.h" 32 #include "breakhandler.h" 33 #include "threadshandler.h" 34 35 #include <coreplugin/icontext.h> 36 #include <projectexplorer/devicesupport/idevice.h> 37 #include <projectexplorer/runcontrol.h> 38 #include <texteditor/textmark.h> 39 #include <utils/fileutils.h> 40 41 #include <QProcess> 42 43 QT_BEGIN_NAMESPACE 44 class QDebug; 45 class QPoint; 46 QT_END_NAMESPACE 47 48 namespace Core { class IOptionsPage; } 49 50 namespace Utils { 51 class MacroExpander; 52 class Perspective; 53 } // Utils 54 55 namespace Debugger { 56 57 class DebuggerRunTool; 58 59 enum DebuggerState 60 { 61 DebuggerNotReady, // Debugger not started 62 63 EngineSetupRequested, // Engine starts 64 EngineSetupFailed, 65 66 EngineRunRequested, 67 EngineRunFailed, 68 69 InferiorUnrunnable, // Used in the core dump adapter 70 71 InferiorRunRequested, // Debuggee requested to run 72 InferiorRunOk, // Debuggee running 73 InferiorRunFailed, // Debuggee not running 74 75 InferiorStopRequested, // Debuggee running, stop requested 76 InferiorStopOk, // Debuggee stopped 77 InferiorStopFailed, // Debuggee not stopped, will kill debugger 78 79 InferiorShutdownRequested, 80 InferiorShutdownFinished, 81 82 EngineShutdownRequested, 83 EngineShutdownFinished, 84 85 DebuggerFinished 86 }; 87 88 DEBUGGER_EXPORT QDebug operator<<(QDebug str, DebuggerState state); 89 90 namespace Internal { 91 92 class DebuggerEnginePrivate; 93 class DebuggerPluginPrivate; 94 class DisassemblerAgent; 95 class MemoryAgent; 96 class WatchItem; 97 class BreakHandler; 98 class BreakpointParameters; 99 class LocationMark; 100 class LogWindow; 101 class ModulesHandler; 102 class RegisterHandler; 103 class PeripheralRegisterHandler; 104 class Section; 105 class SourceFilesHandler; 106 class StackFrame; 107 class StackHandler; 108 class Symbol; 109 class WatchHandler; 110 class WatchTreeView; 111 class DebuggerToolTipContext; 112 class DebuggerToolTipManager; 113 class MemoryViewSetupData; 114 class TerminalRunner; 115 116 class DebuggerRunParameters 117 { 118 public: 119 DebuggerStartMode startMode = NoStartMode; 120 DebuggerCloseMode closeMode = KillAtClose; 121 122 ProjectExplorer::Runnable inferior; 123 QString displayName; // Used in the Snapshots view. 124 Utils::ProcessHandle attachPID; 125 QStringList solibSearchPath; 126 127 // Used by Qml debugging. 128 QUrl qmlServer; 129 130 // Used by general remote debugging. 131 QString remoteChannel; 132 bool useExtendedRemote = false; // Whether to use GDB's target extended-remote or not. 133 Utils::FilePath symbolFile; 134 135 // Used by Mer plugin (3rd party) 136 QMap<QString, QString> sourcePathMap; 137 138 // Used by baremetal plugin 139 QString commandsForReset; // commands used for resetting the inferior 140 bool useContinueInsteadOfRun = false; // if connected to a hw debugger run is not possible but continue is used 141 QString commandsAfterConnect; // additional commands to post after connection to debug target 142 143 // Used by Valgrind 144 QStringList expectedSignals; 145 146 // For QNX debugging 147 bool useCtrlCStub = false; 148 149 // Used by Android to avoid false positives on warnOnRelease 150 bool skipExecutableValidation = false; 151 bool useTargetAsync = false; 152 Utils::FilePaths additionalSearchDirectories; 153 154 // Used by iOS. 155 QString platform; 156 QString deviceSymbolsRoot; 157 bool continueAfterAttach = false; 158 Utils::FilePath sysRoot; 159 160 // Used by general core file debugging. Public access requested in QTCREATORBUG-17158. 161 QString coreFile; 162 163 // Macro-expanded and passed to debugger startup. 164 QString additionalStartupCommands; 165 166 DebuggerEngineType cppEngineType = NoEngineType; 167 168 bool isQmlDebugging = false; 169 bool breakOnMain = false; 170 bool multiProcess = false; // Whether to set detach-on-fork off. 171 bool useTerminal = false; 172 bool runAsRoot = false; 173 174 ProjectExplorer::Runnable debugger; 175 QString overrideStartScript; // Used in attach to core and remote debugging 176 QString startMessage; // First status message shown. 177 QString debugInfoLocation; // Gdb "set-debug-file-directory". 178 QStringList debugSourceLocation; // Gdb "directory" 179 QString qtPackageSourceLocation; 180 bool isSnapshot = false; // Set if created internally. 181 ProjectExplorer::Abi toolChainAbi; 182 183 Utils::FilePath projectSourceDirectory; 184 Utils::FilePaths projectSourceFiles; 185 186 // Used by Script debugging 187 QString interpreter; 188 QString mainScript; 189 190 // Used by AttachCrashedExternal. 191 QString crashParameter; 192 193 bool nativeMixedEnabled = false; 194 195 bool isCppDebugging() const; 196 bool isNativeMixedDebugging() const; 197 198 Utils::MacroExpander *macroExpander = nullptr; 199 200 Utils::optional<int> exitCode = {}; 201 202 // For Debugger testing. 203 int testCase = 0; 204 205 QStringList validationErrors; 206 }; 207 208 class UpdateParameters 209 { 210 public: 211 UpdateParameters(const QString &partialVariable = QString()) : partialVariable(partialVariable)212 partialVariable(partialVariable) {} 213 partialVariables()214 QStringList partialVariables() const 215 { 216 QStringList result; 217 if (!partialVariable.isEmpty()) 218 result.append(partialVariable); 219 return result; 220 } 221 222 QString partialVariable; 223 }; 224 225 class Location 226 { 227 public: 228 Location() = default; Location(quint64 address)229 Location(quint64 address) { m_address = address; } Location(const Utils::FilePath & file)230 Location(const Utils::FilePath &file) { m_fileName = file; } 231 Location(const Utils::FilePath &file, int line, bool marker = true) 232 { m_lineNumber = line; m_fileName = file; m_needsMarker = marker; } 233 Location(const StackFrame &frame, bool marker = true); fileName()234 Utils::FilePath fileName() const { return m_fileName; } functionName()235 QString functionName() const { return m_functionName; } from()236 QString from() const { return m_from; } lineNumber()237 int lineNumber() const { return m_lineNumber; } setNeedsRaise(bool on)238 void setNeedsRaise(bool on) { m_needsRaise = on; } setNeedsMarker(bool on)239 void setNeedsMarker(bool on) { m_needsMarker = on; } setFileName(const Utils::FilePath & fileName)240 void setFileName(const Utils::FilePath &fileName) { m_fileName = fileName; } setUseAssembler(bool on)241 void setUseAssembler(bool on) { m_hasDebugInfo = !on; } needsRaise()242 bool needsRaise() const { return m_needsRaise; } needsMarker()243 bool needsMarker() const { return m_needsMarker; } hasDebugInfo()244 bool hasDebugInfo() const { return m_hasDebugInfo; } canBeDisassembled()245 bool canBeDisassembled() const 246 { return m_address != quint64(-1) || !m_functionName.isEmpty(); } address()247 quint64 address() const { return m_address; } 248 249 private: 250 bool m_needsMarker = false; 251 bool m_needsRaise = true; 252 bool m_hasDebugInfo = true; 253 int m_lineNumber = -1; 254 Utils::FilePath m_fileName; 255 QString m_functionName; 256 QString m_from; 257 quint64 m_address = 0; 258 }; 259 260 class DebuggerEngine : public QObject 261 { 262 Q_OBJECT 263 264 public: 265 DebuggerEngine(); 266 ~DebuggerEngine() override; 267 268 void setRunTool(DebuggerRunTool *runTool); 269 void setRunParameters(const DebuggerRunParameters &runParameters); 270 271 void setRunId(const QString &id); 272 QString runId() const; 273 274 const DebuggerRunParameters &runParameters() const; 275 void setCompanionEngine(DebuggerEngine *engine); 276 void setSecondaryEngine(); 277 278 void start(); 279 280 enum { 281 // Remove need to qualify each use. 282 NeedsTemporaryStop = DebuggerCommand::NeedsTemporaryStop, 283 NeedsFullStop = DebuggerCommand::NeedsFullStop, 284 Discardable = DebuggerCommand::Discardable, 285 ConsoleCommand = DebuggerCommand::ConsoleCommand, 286 NeedsFlush = DebuggerCommand::NeedsFlush, 287 ExitRequest = DebuggerCommand::ExitRequest, 288 RunRequest = DebuggerCommand::RunRequest, 289 LosesChild = DebuggerCommand::LosesChild, 290 InUpdateLocals = DebuggerCommand::InUpdateLocals, 291 NativeCommand = DebuggerCommand::NativeCommand, 292 Silent = DebuggerCommand::Silent 293 }; 294 295 virtual bool canHandleToolTip(const DebuggerToolTipContext &) const; 296 virtual void expandItem(const QString &iname); // Called when item in tree gets expanded. 297 virtual void updateItem(const QString &iname); // Called for fresh watch items. 298 void updateWatchData(const QString &iname); // FIXME: Merge with above. 299 virtual void selectWatchData(const QString &iname); 300 validateRunParameters(DebuggerRunParameters &)301 virtual void validateRunParameters(DebuggerRunParameters &) {} prepareForRestart()302 virtual void prepareForRestart() {} abortDebuggerProcess()303 virtual void abortDebuggerProcess() {} // second attempt 304 305 virtual void watchPoint(const QPoint &pnt); 306 virtual void runCommand(const DebuggerCommand &cmd); 307 virtual void openMemoryView(const MemoryViewSetupData &data); 308 virtual void fetchMemory(MemoryAgent *, quint64 addr, quint64 length); 309 virtual void changeMemory(MemoryAgent *, quint64 addr, const QByteArray &data); 310 virtual void updateMemoryViews(); 311 virtual void openDisassemblerView(const Internal::Location &location); 312 virtual void fetchDisassembler(Internal::DisassemblerAgent *); 313 virtual void activateFrame(int index); 314 315 virtual void reloadModules(); 316 virtual void examineModules(); 317 virtual void loadSymbols(const QString &moduleName); 318 virtual void loadSymbolsForStack(); 319 virtual void loadAllSymbols(); 320 virtual void requestModuleSymbols(const QString &moduleName); 321 virtual void requestModuleSections(const QString &moduleName); 322 323 virtual void reloadRegisters(); 324 virtual void reloadPeripheralRegisters(); 325 virtual void reloadSourceFiles(); 326 virtual void reloadFullStack(); 327 virtual void loadAdditionalQmlStack(); 328 virtual void reloadDebuggingHelpers(); 329 330 virtual void setRegisterValue(const QString &name, const QString &value); 331 virtual void setPeripheralRegisterValue(quint64 address, quint64 value); 332 virtual void addOptionPages(QList<Core::IOptionsPage*> *) const; 333 virtual bool hasCapability(unsigned cap) const = 0; debugLastCommand()334 virtual void debugLastCommand() {} 335 336 virtual QString qtNamespace() const; 337 void setQtNamespace(const QString &ns); 338 339 virtual void createSnapshot(); 340 virtual void updateAll(); 341 virtual void updateLocals(); 342 343 Core::Context debuggerContext() const; languageContext()344 virtual Core::Context languageContext() const { return {}; } 345 QString displayName() const; 346 347 virtual bool acceptsBreakpoint(const BreakpointParameters &bp) const = 0; 348 virtual void insertBreakpoint(const Breakpoint &bp) = 0; 349 virtual void removeBreakpoint(const Breakpoint &bp) = 0; 350 virtual void updateBreakpoint(const Breakpoint &bp) = 0; 351 virtual void enableSubBreakpoint(const SubBreakpoint &sbp, bool enabled); 352 acceptsDebuggerCommands()353 virtual bool acceptsDebuggerCommands() const { return true; } 354 virtual void executeDebuggerCommand(const QString &command); 355 356 virtual void assignValueInDebugger(WatchItem *item, 357 const QString &expr, const QVariant &value); 358 virtual void selectThread(const Internal::Thread &thread) = 0; 359 executeRecordReverse(bool)360 virtual void executeRecordReverse(bool) {} executeReverse(bool)361 virtual void executeReverse(bool) {} 362 363 ModulesHandler *modulesHandler() const; 364 RegisterHandler *registerHandler() const; 365 PeripheralRegisterHandler *peripheralRegisterHandler() const; 366 StackHandler *stackHandler() const; 367 ThreadsHandler *threadsHandler() const; 368 WatchHandler *watchHandler() const; 369 SourceFilesHandler *sourceFilesHandler() const; 370 BreakHandler *breakHandler() const; 371 LogWindow *logWindow() const; 372 DisassemblerAgent *disassemblerAgent() const; 373 374 void progressPing(); 375 bool debuggerActionsEnabled() const; 376 virtual bool companionPreventsActions() const; 377 378 bool operatesByInstruction() const; 379 virtual void operateByInstructionTriggered(bool on); // FIXME: Remove. 380 381 DebuggerState state() const; 382 bool isDying() const; 383 384 static QString stateName(int s); 385 386 void notifyExitCode(int code); 387 void notifyInferiorPid(const Utils::ProcessHandle &pid); 388 qint64 inferiorPid() const; 389 390 bool isReverseDebugging() const; 391 void handleBeginOfRecordingReached(); 392 void handleRecordingFailed(); 393 void handleRecordReverse(bool); 394 void handleReverseDirection(bool); 395 396 // Convenience 397 void showMessage(const QString &msg, int channel = LogDebug, int timeout = -1) const; 398 void showStatusMessage(const QString &msg, int timeout = -1) const; 399 400 virtual void resetLocation(); 401 virtual void gotoLocation(const Internal::Location &location); 402 void gotoCurrentLocation(); 403 virtual void quitDebugger(); // called when pressing the stop button 404 void abortDebugger(); 405 void updateUi(bool isCurrentEngine); 406 407 bool isPrimaryEngine() const; 408 409 virtual bool canDisplayTooltip() const; 410 411 QString expand(const QString &string) const; 412 QString nativeStartupCommands() const; 413 Utils::Perspective *perspective() const; 414 void updateMarkers(); 415 416 void updateToolTips(); 417 DebuggerToolTipManager *toolTipManager(); 418 419 signals: 420 void engineStarted(); 421 void engineFinished(); 422 void requestRunControlFinish(); 423 void requestRunControlStop(); 424 void attachToCoreRequested(const QString &coreFile); 425 void appendMessageRequested(const QString &msg, 426 Utils::OutputFormat format, 427 bool appendNewLine) const; 428 429 protected: 430 void notifyEngineSetupOk(); 431 void notifyEngineSetupFailed(); 432 void notifyEngineRunFailed(); 433 434 void notifyEngineRunAndInferiorRunOk(); 435 void notifyEngineRunAndInferiorStopOk(); 436 void notifyEngineRunOkAndInferiorUnrunnable(); // Called by CoreAdapter. 437 438 // Use notifyInferiorRunRequested() plus notifyInferiorRunOk() instead. 439 // void notifyInferiorSpontaneousRun(); 440 441 void notifyInferiorRunRequested(); 442 void notifyInferiorRunOk(); 443 void notifyInferiorRunFailed(); 444 445 void notifyInferiorIll(); 446 void notifyInferiorExited(); 447 448 void notifyInferiorStopOk(); 449 void notifyInferiorSpontaneousStop(); 450 void notifyInferiorStopFailed(); 451 452 public: 453 void updateState(); 454 QString formatStartParameters() const; 455 WatchTreeView *inspectorView(); 456 void updateLocalsWindow(bool showReturn); 457 void raiseWatchersWindow(); 458 QString debuggerName() const; 459 460 bool isRegistersWindowVisible() const; 461 bool isPeripheralRegistersWindowVisible() const; 462 bool isModulesWindowVisible() const; 463 464 void openMemoryEditor(); 465 466 static void showModuleSymbols(const QString &moduleName, const QVector<Symbol> &symbols); 467 static void showModuleSections(const QString &moduleName, const QVector<Section> §ions); 468 469 void handleExecDetach(); 470 void handleExecContinue(); 471 void handleExecInterrupt(); 472 void handleUserStop(); 473 void handleAbort(); 474 void handleReset(); 475 void handleExecStepIn(); 476 void handleExecStepOver(); 477 void handleExecStepOut(); 478 void handleExecReturn(); 479 void handleExecJumpToLine(); 480 void handleExecRunToLine(); 481 void handleExecRunToSelectedFunction(); 482 void handleAddToWatchWindow(); 483 void handleFrameDown(); 484 void handleFrameUp(); 485 486 // Breakpoint state transitions 487 void notifyBreakpointInsertProceeding(const Breakpoint &bp); 488 void notifyBreakpointInsertOk(const Breakpoint &bp); 489 void notifyBreakpointInsertFailed(const Breakpoint &bp); 490 void notifyBreakpointChangeOk(const Breakpoint &bp); 491 void notifyBreakpointChangeProceeding(const Breakpoint &bp); 492 void notifyBreakpointChangeFailed(const Breakpoint &bp); 493 void notifyBreakpointPending(const Breakpoint &bp); 494 void notifyBreakpointRemoveProceeding(const Breakpoint &bp); 495 void notifyBreakpointRemoveOk(const Breakpoint &bp); 496 void notifyBreakpointRemoveFailed(const Breakpoint &bp); 497 void notifyBreakpointNeedsReinsertion(const Breakpoint &bp); 498 499 protected: 500 void setDebuggerName(const QString &name); 501 void notifyDebuggerProcessFinished(int exitCode, QProcess::ExitStatus exitStatus, 502 const QString &backendName); 503 504 virtual void setState(DebuggerState state, bool forced = false); 505 506 void notifyInferiorShutdownFinished(); 507 508 void notifyEngineSpontaneousShutdown(); 509 void notifyEngineShutdownFinished(); 510 511 void notifyEngineIll(); 512 513 virtual void setupEngine() = 0; 514 virtual void shutdownInferior() = 0; 515 virtual void shutdownEngine() = 0; resetInferior()516 virtual void resetInferior() {} 517 detachDebugger()518 virtual void detachDebugger() {} 519 virtual void executeStepOver(bool /*byInstruction*/ = false) {} 520 virtual void executeStepIn(bool /*byInstruction*/ = false) {} executeStepOut()521 virtual void executeStepOut() {} executeReturn()522 virtual void executeReturn() {} 523 continueInferior()524 virtual void continueInferior() {} interruptInferior()525 virtual void interruptInferior() {} 526 void requestInterruptInferior(); 527 executeRunToLine(const Internal::ContextData &)528 virtual void executeRunToLine(const Internal::ContextData &) {} executeRunToFunction(const QString &)529 virtual void executeRunToFunction(const QString &) {} executeJumpToLine(const Internal::ContextData &)530 virtual void executeJumpToLine(const Internal::ContextData &) {} 531 532 virtual void frameUp(); 533 virtual void frameDown(); 534 535 virtual void doUpdateLocals(const UpdateParameters ¶ms); 536 537 TerminalRunner *terminal() const; 538 539 static QString msgStopped(const QString &reason = QString()); 540 static QString msgStoppedBySignal(const QString &meaning, const QString &name); 541 static QString msgStoppedByException(const QString &description, 542 const QString &threadId); 543 static QString msgInterrupted(); 544 bool showStoppedBySignalMessageBox(const QString meaning, QString name); 545 void showStoppedByExceptionMessageBox(const QString &description); 546 547 void updateLocalsView(const GdbMi &all); 548 void checkState(DebuggerState state, const char *file, int line); 549 bool isNativeMixedEnabled() const; 550 bool isNativeMixedActive() const; 551 bool isNativeMixedActiveFrame() const; 552 void startDying() const; 553 554 ProjectExplorer::IDevice::ConstPtr device() const; 555 DebuggerEngine *companionEngine() const; 556 557 private: 558 friend class DebuggerPluginPrivate; 559 friend class DebuggerEnginePrivate; 560 friend class LocationMark; 561 friend class PeripheralRegisterHandler; 562 DebuggerEnginePrivate *d; 563 }; 564 565 class CppDebuggerEngine : public DebuggerEngine 566 { 567 public: CppDebuggerEngine()568 CppDebuggerEngine() {} ~CppDebuggerEngine()569 ~CppDebuggerEngine() override {} 570 571 void validateRunParameters(DebuggerRunParameters &rp) override; 572 Core::Context languageContext() const override; 573 }; 574 575 class LocationMark : public TextEditor::TextMark 576 { 577 public: 578 LocationMark(DebuggerEngine *engine, const Utils::FilePath &file, int line); removedFromEditor()579 void removedFromEditor() override { updateLineNumber(0); } 580 581 void updateIcon(); 582 583 private: 584 bool isDraggable() const override; 585 void dragToLine(int line) override; 586 587 QPointer<DebuggerEngine> m_engine; 588 }; 589 590 } // namespace Internal 591 } // namespace Debugger 592 593 Q_DECLARE_METATYPE(Debugger::Internal::UpdateParameters) 594 Q_DECLARE_METATYPE(Debugger::Internal::ContextData) 595