// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "debuggeractions.h" #include "commonoptionspage.h" #include "debuggerinternalconstants.h" #include "debuggertr.h" #include "gdb/gdbsettings.h" #include #include #include #include #include #include using namespace Utils; namespace Debugger::Internal { // DebuggerSettings DebuggerSettings &settings() { static DebuggerSettings settings; return settings; } DebuggerSettings::DebuggerSettings() : useAlternatingRowColors{commonSettings().useAlternatingRowColors}, useAnnotationsInMainEditor{commonSettings().useAnnotationsInMainEditor}, useToolTipsInMainEditor{commonSettings().useToolTipsInMainEditor}, closeSourceBuffersOnExit{commonSettings().closeSourceBuffersOnExit}, closeMemoryBuffersOnExit{commonSettings().closeMemoryBuffersOnExit}, raiseOnInterrupt{commonSettings().raiseOnInterrupt}, breakpointsFullPathByDefault{commonSettings().breakpointsFullPathByDefault}, warnOnReleaseBuilds{commonSettings().warnOnReleaseBuilds}, maximalStackDepth{commonSettings().maximalStackDepth}, fontSizeFollowsEditor{commonSettings().fontSizeFollowsEditor}, switchModeOnExit{commonSettings().switchModeOnExit}, showQmlObjectTree{commonSettings().showQmlObjectTree}, stationaryEditorWhileStepping{commonSettings().stationaryEditorWhileStepping}, forceLoggingToConsole{commonSettings().forceLoggingToConsole}, showUnsupportedBreakpointWarning{commonSettings().showUnsupportedBreakpointWarning}, sourcePathMap{commonSettings().sourcePathMap}, registerForPostMortem{*commonSettings().registerForPostMortem}, gdbWatchdogTimeout{gdbSettings().gdbWatchdogTimeout}, skipKnownFrames{gdbSettings().skipKnownFrames}, useMessageBoxForSignals{gdbSettings().useMessageBoxForSignals}, adjustBreakpointLocations{gdbSettings().adjustBreakpointLocations}, useDynamicType{gdbSettings().useDynamicType}, loadGdbInit{gdbSettings().loadGdbInit}, loadGdbDumpers{gdbSettings().loadGdbDumpers}, intelFlavor{gdbSettings().intelFlavor}, usePseudoTracepoints{gdbSettings().usePseudoTracepoints}, useIndexCache{gdbSettings().useIndexCache}, useDebugInfoD{gdbSettings().useDebugInfoD}, gdbStartupCommands{gdbSettings().gdbStartupCommands}, gdbPostAttachCommands{gdbSettings().gdbPostAttachCommands}, targetAsync{gdbSettings().targetAsync}, autoEnrichParameters{gdbSettings().autoEnrichParameters}, breakOnThrow{gdbSettings().breakOnThrow}, breakOnCatch{gdbSettings().breakOnCatch}, breakOnWarning{gdbSettings().breakOnWarning}, breakOnFatal{gdbSettings().breakOnFatal}, breakOnAbort{gdbSettings().breakOnAbort}, enableReverseDebugging{gdbSettings().enableReverseDebugging}, multiInferior{gdbSettings().multiInferior}, // Page 4 useDebuggingHelpers{localsAndExpressionSettings().useDebuggingHelpers}, allowInferiorCalls{localsAndExpressionSettings().allowInferiorCalls}, useCodeModel{localsAndExpressionSettings().useCodeModel}, showThreadNames{localsAndExpressionSettings().showThreadNames}, extraDumperFile{localsAndExpressionSettings().extraDumperFile}, // For loading a file. Recommended. extraDumperCommands{localsAndExpressionSettings().extraDumperCommands}, // To modify an existing setup. showStdNamespace{localsAndExpressionSettings().showStdNamespace}, showQtNamespace{localsAndExpressionSettings().showQtNamespace}, showQObjectNames{localsAndExpressionSettings().showQObjectNames}, maximalStringLength{localsAndExpressionSettings().maximalStringLength}, displayStringLimit{localsAndExpressionSettings().displayStringLimit}, defaultArraySize{localsAndExpressionSettings().defaultArraySize} { const Key debugModeGroup("DebugMode"); const Key cdbSettingsGroup("CDB2"); settingsDialog.setLabelText(Tr::tr("Configure Debugger...")); /* groupBoxPluginDebugging = new QGroupBox(q); groupBoxPluginDebugging->setTitle(Tr::tr( "Behavior of Breakpoint Setting in Plugins")); radioButtonAllPluginBreakpoints = new QRadioButton(groupBoxPluginDebugging); radioButtonAllPluginBreakpoints->setText(Tr::tr( "Always try to set breakpoints in plugins automatically")); radioButtonAllPluginBreakpoints->setToolTip(Tr::tr( "This is the slowest but safest option.")); radioButtonSelectedPluginBreakpoints = new QRadioButton(groupBoxPluginDebugging); radioButtonSelectedPluginBreakpoints->setText(Tr::tr( "Try to set breakpoints in selected plugins")); radioButtonNoPluginBreakpoints = new QRadioButton(groupBoxPluginDebugging); radioButtonNoPluginBreakpoints->setText(Tr::tr( "Never set breakpoints in plugins automatically")); lineEditSelectedPluginBreakpointsPattern = new QLineEdit(groupBoxPluginDebugging); labelSelectedPluginBreakpoints = new QLabel(groupBoxPluginDebugging); labelSelectedPluginBreakpoints->setText(Tr::tr( "Matching regular expression: ")); */ // // View // alwaysAdjustColumnWidths.setLabelText(Tr::tr("Always Adjust View Column Widths to Contents")); alwaysAdjustColumnWidths.setSettingsKey(debugModeGroup, "AlwaysAdjustColumnWidths"); alwaysAdjustColumnWidths.setDefaultValue(true); logTimeStamps.setLabelText(Tr::tr("Log Time Stamps")); logTimeStamps.setSettingsKey(debugModeGroup, "LogTimeStamps"); autoDerefPointers.setLabelText(Tr::tr("Dereference Pointers Automatically")); autoDerefPointers.setDefaultValue(true); autoDerefPointers.setSettingsKey(debugModeGroup, "AutoDerefPointers"); autoDerefPointers.setToolTip( "

" + Tr::tr("This switches the Locals and Expressions views to " "automatically dereference pointers. This saves a level in the " "tree view, but also loses data for the now-missing intermediate " "level.")); // // Cdb Options // cdbAdditionalArguments.setSettingsKey(cdbSettingsGroup, "AdditionalArguments"); cdbAdditionalArguments.setDisplayStyle(StringAspect::LineEditDisplay); cdbAdditionalArguments.setLabelText(Tr::tr("Additional arguments:")); cdbSymbolPaths.setSettingsKey(cdbSettingsGroup, "SymbolPaths"); cdbSourcePaths.setSettingsKey(cdbSettingsGroup, "SourcePaths"); cdbBreakEvents.setSettingsKey(cdbSettingsGroup, "BreakEvent"); cdbBreakOnCrtDbgReport.setSettingsKey(cdbSettingsGroup, "BreakOnCrtDbgReport"); cdbBreakOnCrtDbgReport.setLabelText(msgSetBreakpointAtFunction(Constants::CRT_DEBUG_REPORT)); cdbBreakOnCrtDbgReport.setToolTip(msgSetBreakpointAtFunctionToolTip(Constants::CRT_DEBUG_REPORT, Tr::tr("Catches runtime error messages caused by assert(), for example."))); useCdbConsole.setSettingsKey(cdbSettingsGroup, "CDB_Console"); useCdbConsole.setToolTip("

" + Tr::tr( "Uses CDB's native console for console applications. " "This overrides the setting in Environment > System. " "The native console does not prompt on application exit. " "It is suitable for diagnosing cases in which the application does not " "start up properly in the configured console and the subsequent attach fails.") + "

"); useCdbConsole.setLabelText(Tr::tr("Use CDB &console")); cdbBreakPointCorrection.setSettingsKey(cdbSettingsGroup, "BreakpointCorrection"); cdbBreakPointCorrection.setDefaultValue(true); cdbBreakPointCorrection.setToolTip("

" + Tr::tr( "Attempts to correct the location of a breakpoint based on file and line number should " "it be in a comment or in a line for which no code is generated. " "The correction is based on the code model.") + "

"); cdbBreakPointCorrection.setLabelText(Tr::tr("Correct breakpoint location")); cdbUsePythonDumper.setSettingsKey(cdbSettingsGroup, "UsePythonDumper"); cdbUsePythonDumper.setDefaultValue(true); cdbUsePythonDumper.setLabelText(Tr::tr("Use Python dumper")); firstChanceExceptionTaskEntry.setSettingsKey(cdbSettingsGroup, "FirstChanceExceptionTaskEntry"); firstChanceExceptionTaskEntry.setDefaultValue(true); firstChanceExceptionTaskEntry.setLabelText(Tr::tr("First chance exceptions")); secondChanceExceptionTaskEntry.setSettingsKey(cdbSettingsGroup, "SecondChanceExceptionTaskEntry"); secondChanceExceptionTaskEntry.setDefaultValue(true); secondChanceExceptionTaskEntry.setLabelText(Tr::tr("Second chance exceptions")); ignoreFirstChanceAccessViolation.setSettingsKey(cdbSettingsGroup, "IgnoreFirstChanceAccessViolation"); ignoreFirstChanceAccessViolation.setLabelText(Tr::tr("Ignore first chance access violations")); enableHeapDebugging.setSettingsKey(cdbSettingsGroup, "EnableHeapDebugging"); enableHeapDebugging.setLabelText(Tr::tr("Enable heap debugging")); enableHeapDebugging.setToolTip( "

" + Tr::tr("Allocate memory using the debug heap rather than the normal heap. The debug heap " "enables additional checks to help diagnose heap related bugs. However it comes " "at a performance cost when allocating memory in the debugged process.")); // // Locals & Watchers sortStructMembers.setSettingsKey(debugModeGroup, "SortStructMembers"); sortStructMembers.setDisplayName(Tr::tr("Sort Members of Classes and Structs Alphabetically")); sortStructMembers.setLabelText(Tr::tr("Sort members of classes and structs alphabetically")); sortStructMembers.setDefaultValue(true); // // Breakpoints // synchronizeBreakpoints.setLabelText(Tr::tr("Synchronize Breakpoints")); autoQuit.setSettingsKey(debugModeGroup, "AutoQuit"); autoQuit.setLabelText(Tr::tr("Automatically Quit Debugger")); useToolTipsInLocalsView.setSettingsKey(debugModeGroup, "UseToolTipsInLocalsView"); useToolTipsInLocalsView.setLabelText(Tr::tr("Use Tooltips in Locals View when Debugging")); useToolTipsInLocalsView.setToolTip("

" + Tr::tr("Enables tooltips in the locals " "view during debugging.")); useToolTipsInBreakpointsView.setSettingsKey(debugModeGroup, "UseToolTipsInBreakpointsView"); useToolTipsInBreakpointsView.setLabelText(Tr::tr("Use Tooltips in Breakpoints View when Debugging")); useToolTipsInBreakpointsView.setToolTip("

" + Tr::tr("Enables tooltips in the breakpoints " "view during debugging.")); useToolTipsInStackView.setSettingsKey(debugModeGroup, "UseToolTipsInStackView"); useToolTipsInStackView.setLabelText(Tr::tr("Use Tooltips in Stack View when Debugging")); useToolTipsInStackView.setToolTip("

" + Tr::tr("Enables tooltips in the stack " "view during debugging.")); useToolTipsInStackView.setDefaultValue(true); allPluginBreakpoints.setSettingsKey(debugModeGroup, "AllPluginBreakpoints"); allPluginBreakpoints.setDefaultValue(true); selectedPluginBreakpoints.setSettingsKey(debugModeGroup, "SelectedPluginBreakpoints"); noPluginBreakpoints.setSettingsKey(debugModeGroup, "NoPluginBreakpoints"); selectedPluginBreakpointsPattern.setSettingsKey(debugModeGroup, "SelectedPluginBreakpointsPattern"); selectedPluginBreakpointsPattern.setDefaultValue(QString(".*")); expandStack.setLabelText(Tr::tr("Reload Full Stack")); createFullBacktrace.setLabelText(Tr::tr("Create Full Backtrace")); // // QML Tools // const Key qmlInspectorGroup = "QML.Inspector"; showAppOnTop.setSettingsKey(qmlInspectorGroup, "QmlInspector.ShowAppOnTop"); // Page 5 page5.registerAspect(&cdbAdditionalArguments); page5.registerAspect(&cdbBreakEvents); page5.registerAspect(&cdbBreakOnCrtDbgReport); page5.registerAspect(&useCdbConsole); page5.registerAspect(&cdbBreakPointCorrection); page5.registerAspect(&cdbUsePythonDumper); page5.registerAspect(&firstChanceExceptionTaskEntry); page5.registerAspect(&secondChanceExceptionTaskEntry); page5.registerAspect(&ignoreFirstChanceAccessViolation); page5.registerAspect(&enableHeapDebugging); // Page 6 page6.registerAspect(&cdbSymbolPaths); page6.registerAspect(&cdbSourcePaths); // Pageless all.registerAspect(&autoDerefPointers); all.registerAspect(&useToolTipsInLocalsView); all.registerAspect(&alwaysAdjustColumnWidths); all.registerAspect(&useToolTipsInBreakpointsView); all.registerAspect(&useToolTipsInStackView); all.registerAspect(&logTimeStamps); all.registerAspect(&sortStructMembers); // Collect all all.registerAspects(page5); all.registerAspects(page6); all.forEachAspect([](BaseAspect *aspect) { aspect->setAutoApply(false); // FIXME: Make the positioning part of the LayoutBuilder later if (auto boolAspect = dynamic_cast(aspect)) boolAspect->setLabelPlacement(BoolAspect::LabelPlacement::AtCheckBox); }); all.readSettings(); QObject::connect(Core::ICore::instance(), &Core::ICore::saveSettingsRequested, &all, &AspectContainer::writeSettings); } QString DebuggerSettings::dump() { QStringList msg; settings().all.forEachAspect([&msg](BaseAspect *aspect) { Key key = aspect->settingsKey(); if (!key.isEmpty()) { const int pos = key.view().indexOf('/'); if (pos >= 0) key = key.toByteArray().mid(pos); const QString current = aspect->variantValue().toString(); const QString default_ = aspect->defaultVariantValue().toString(); QString setting = stringFromKey(key) + ": " + current + " (default: " + default_ + ')'; if (current != default_) setting += " ***"; msg << setting; } }); msg.sort(); return "Debugger settings:\n" + msg.join('\n'); } } // Debugger::Internal