CDB: Add setting to add breakpoint at CrtDbgReport().

- Factor out message/tooltips for breakpoints on functions.
- Add stringlist of break functions to CdbOptions.
- Set breakpoints with module, ignore response.

Change-Id: If5cf7647b190057c18d8499b9f4862696610e4f6
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Friedemann Kleint
2012-08-28 14:37:18 +02:00
committed by hjk
parent d07e7d2aab
commit 5409d2d1d3
8 changed files with 111 additions and 13 deletions

View File

@@ -775,12 +775,59 @@ void CdbEngine::setupInferior()
postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid); postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid);
} }
static QByteArray msvcRunTime(const Abi::OSFlavor flavour)
{
switch (flavour) {
case Abi::WindowsMsvc2005Flavor:
return "MSVCR80";
case Abi::WindowsMsvc2008Flavor:
return "MSVCR90";
case Abi::WindowsMsvc2010Flavor:
return "MSVCR100";
case Abi::WindowsMsvc2012Flavor:
return "MSVCR110"; // #FIXME: VS2012 beta, will probably be 12 in final?
default:
break;
}
return "MSVCRT"; // MinGW, others.
}
static QByteArray breakAtFunctionCommand(const QByteArray &function,
const QByteArray &module = QByteArray())
{
QByteArray result = "bu ";
if (!module.isEmpty()) {
result += module;
result += '!';
}
result += function;
return result;
}
void CdbEngine::runEngine() void CdbEngine::runEngine()
{ {
if (debug) if (debug)
qDebug("runEngine"); qDebug("runEngine");
foreach (const QString &breakEvent, m_options->breakEvents) foreach (const QString &breakEvent, m_options->breakEvents)
postCommand(QByteArray("sxe ") + breakEvent.toAscii(), 0); postCommand(QByteArray("sxe ") + breakEvent.toAscii(), 0);
// Break functions: each function must be fully qualified,
// else the debugger will slow down considerably.
foreach (const QString &breakFunctionS, m_options->breakFunctions) {
const QByteArray breakFunction = breakFunctionS.toLatin1();
if (breakFunction == CdbOptions::crtDbgReport) {
// CrtDbgReport(): Add MSVC runtime (debug, release)
// and stop at Wide character version as well
const QByteArray module = msvcRunTime(startParameters().toolChainAbi.osFlavor());
const QByteArray debugModule = module + 'D';
const QByteArray wideFunc = breakFunction + 'W';
postCommand(breakAtFunctionCommand(breakFunction, module), 0);
postCommand(breakAtFunctionCommand(wideFunc, module), 0);
postCommand(breakAtFunctionCommand(breakFunction, debugModule), 0);
postCommand(breakAtFunctionCommand(wideFunc, debugModule), 0);
} else {
postCommand(breakAtFunctionCommand(breakFunction), 0);
}
}
if (startParameters().startMode == AttachCore) { if (startParameters().startMode == AttachCore) {
QTC_ASSERT(!m_coreStopReason.isNull(), return; ); QTC_ASSERT(!m_coreStopReason.isNull(), return; );
notifyInferiorUnrunnable(); notifyInferiorUnrunnable();
@@ -2990,6 +3037,8 @@ void CdbEngine::handleBreakPoints(const GdbMi &value)
qPrintable(reportedResponse.toString())); qPrintable(reportedResponse.toString()));
if (reportedResponse.id.isValid() && !reportedResponse.pending) { if (reportedResponse.id.isValid() && !reportedResponse.pending) {
const BreakpointModelId mid = handler->findBreakpointByResponseId(reportedResponse.id); const BreakpointModelId mid = handler->findBreakpointByResponseId(reportedResponse.id);
if (!mid.isValid() && reportedResponse.type == BreakpointByFunction)
continue; // Breakpoints from options, CrtDbgReport() and others.
QTC_ASSERT(mid.isValid(), continue); QTC_ASSERT(mid.isValid(), continue);
const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(mid); const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(mid);
if (it != m_pendingBreakpointMap.end()) { if (it != m_pendingBreakpointMap.end()) {

View File

@@ -36,6 +36,7 @@ static const char settingsGroupC[] = "CDB2";
static const char symbolPathsKeyC[] = "SymbolPaths"; static const char symbolPathsKeyC[] = "SymbolPaths";
static const char sourcePathsKeyC[] = "SourcePaths"; static const char sourcePathsKeyC[] = "SourcePaths";
static const char breakEventKeyC[] = "BreakEvent"; static const char breakEventKeyC[] = "BreakEvent";
static const char breakFunctionsKeyC[] = "BreakFunctions";
static const char additionalArgumentsKeyC[] = "AdditionalArguments"; static const char additionalArgumentsKeyC[] = "AdditionalArguments";
static const char cdbConsoleKeyC[] = "CDB_Console"; static const char cdbConsoleKeyC[] = "CDB_Console";
static const char breakpointCorrectionKeyC[] = "BreakpointCorrection"; static const char breakpointCorrectionKeyC[] = "BreakpointCorrection";
@@ -43,6 +44,8 @@ static const char breakpointCorrectionKeyC[] = "BreakpointCorrection";
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
const char *CdbOptions::crtDbgReport = "CrtDbgReport";
CdbOptions::CdbOptions() : cdbConsole(false), breakpointCorrection(true) CdbOptions::CdbOptions() : cdbConsole(false), breakpointCorrection(true)
{ {
} }
@@ -57,6 +60,8 @@ void CdbOptions::clear()
symbolPaths.clear(); symbolPaths.clear();
sourcePaths.clear(); sourcePaths.clear();
cdbConsole = false; cdbConsole = false;
breakEvents.clear();
breakFunctions.clear();
} }
QStringList CdbOptions::oldEngineSymbolPaths(const QSettings *s) QStringList CdbOptions::oldEngineSymbolPaths(const QSettings *s)
@@ -72,6 +77,7 @@ void CdbOptions::fromSettings(QSettings *s)
symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList(); symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList();
sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList(); sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList();
breakEvents = s->value(keyRoot + QLatin1String(breakEventKeyC), QStringList()).toStringList(); breakEvents = s->value(keyRoot + QLatin1String(breakEventKeyC), QStringList()).toStringList();
breakFunctions = s->value(keyRoot + QLatin1String(breakFunctionsKeyC), QStringList()).toStringList();
cdbConsole = s->value(keyRoot + QLatin1String(cdbConsoleKeyC), QVariant(false)).toBool(); cdbConsole = s->value(keyRoot + QLatin1String(cdbConsoleKeyC), QVariant(false)).toBool();
breakpointCorrection = s->value(keyRoot + QLatin1String(breakpointCorrectionKeyC), QVariant(true)).toBool(); breakpointCorrection = s->value(keyRoot + QLatin1String(breakpointCorrectionKeyC), QVariant(true)).toBool();
} }
@@ -82,6 +88,7 @@ void CdbOptions::toSettings(QSettings *s) const
s->setValue(QLatin1String(symbolPathsKeyC), symbolPaths); s->setValue(QLatin1String(symbolPathsKeyC), symbolPaths);
s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths); s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths);
s->setValue(QLatin1String(breakEventKeyC), breakEvents); s->setValue(QLatin1String(breakEventKeyC), breakEvents);
s->setValue(QLatin1String(breakFunctionsKeyC), breakFunctions);
s->setValue(QLatin1String(additionalArgumentsKeyC), additionalArguments); s->setValue(QLatin1String(additionalArgumentsKeyC), additionalArguments);
s->setValue(QLatin1String(cdbConsoleKeyC), QVariant(cdbConsole)); s->setValue(QLatin1String(cdbConsoleKeyC), QVariant(cdbConsole));
s->setValue(QLatin1String(breakpointCorrectionKeyC), QVariant(breakpointCorrection)); s->setValue(QLatin1String(breakpointCorrectionKeyC), QVariant(breakpointCorrection));
@@ -95,7 +102,8 @@ bool CdbOptions::equals(const CdbOptions &rhs) const
&& additionalArguments == rhs.additionalArguments && additionalArguments == rhs.additionalArguments
&& symbolPaths == rhs.symbolPaths && symbolPaths == rhs.symbolPaths
&& sourcePaths == rhs.sourcePaths && sourcePaths == rhs.sourcePaths
&& breakEvents == rhs.breakEvents; && breakEvents == rhs.breakEvents
&& breakFunctions == rhs.breakFunctions;
} }
} // namespace Internal } // namespace Internal

View File

@@ -62,10 +62,13 @@ public:
QStringList sourcePaths; QStringList sourcePaths;
// Events to break on (Command 'sxe' with abbreviation and optional parameter) // Events to break on (Command 'sxe' with abbreviation and optional parameter)
QStringList breakEvents; QStringList breakEvents;
QStringList breakFunctions;
// Launch CDB's own console instead of Qt Creator's // Launch CDB's own console instead of Qt Creator's
bool cdbConsole; bool cdbConsole;
// Perform code-model based correction of breakpoint location. // Perform code-model based correction of breakpoint location.
bool breakpointCorrection; bool breakpointCorrection;
static const char *crtDbgReport;
}; };
inline bool operator==(const CdbOptions &s1, const CdbOptions &s2) inline bool operator==(const CdbOptions &s1, const CdbOptions &s2)

View File

@@ -30,6 +30,7 @@
#include "cdboptionspage.h" #include "cdboptionspage.h"
#include "cdboptions.h" #include "cdboptions.h"
#include "commonoptionspage.h"
#include "debuggerinternalconstants.h" #include "debuggerinternalconstants.h"
#include "cdbengine.h" #include "cdbengine.h"
@@ -176,6 +177,11 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
eventLayout->setContentsMargins(margins); eventLayout->setContentsMargins(margins);
eventLayout->addWidget(m_breakEventWidget); eventLayout->addWidget(m_breakEventWidget);
m_ui.eventGroupBox->setLayout(eventLayout); m_ui.eventGroupBox->setLayout(eventLayout);
m_ui.breakCrtDbgReportCheckBox
->setText(CommonOptionsPage::msgSetBreakpointAtFunction(CdbOptions::crtDbgReport));
const QString hint = tr("This is useful to catch runtime error messages, for example caused by assert().");
m_ui.breakCrtDbgReportCheckBox
->setToolTip(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip(CdbOptions::crtDbgReport, hint));
} }
void CdbOptionsPageWidget::setOptions(CdbOptions &o) void CdbOptionsPageWidget::setOptions(CdbOptions &o)
@@ -186,6 +192,7 @@ void CdbOptionsPageWidget::setOptions(CdbOptions &o)
m_breakEventWidget->setBreakEvents(o.breakEvents); m_breakEventWidget->setBreakEvents(o.breakEvents);
m_ui.consoleCheckBox->setChecked(o.cdbConsole); m_ui.consoleCheckBox->setChecked(o.cdbConsole);
m_ui.breakpointCorrectionCheckBox->setChecked(o.breakpointCorrection); m_ui.breakpointCorrectionCheckBox->setChecked(o.breakpointCorrection);
m_ui.breakCrtDbgReportCheckBox->setChecked(o.breakFunctions.contains(QLatin1String(CdbOptions::crtDbgReport)));
} }
CdbOptions CdbOptionsPageWidget::options() const CdbOptions CdbOptionsPageWidget::options() const
@@ -197,6 +204,8 @@ CdbOptions CdbOptionsPageWidget::options() const
rc.breakEvents = m_breakEventWidget->breakEvents(); rc.breakEvents = m_breakEventWidget->breakEvents();
rc.cdbConsole = m_ui.consoleCheckBox->isChecked(); rc.cdbConsole = m_ui.consoleCheckBox->isChecked();
rc.breakpointCorrection = m_ui.breakpointCorrectionCheckBox->isChecked(); rc.breakpointCorrection = m_ui.breakpointCorrectionCheckBox->isChecked();
if (m_ui.breakCrtDbgReportCheckBox->isChecked())
rc.breakFunctions.push_back(QLatin1String(CdbOptions::crtDbgReport));
return rc; return rc;
} }

View File

@@ -120,6 +120,18 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QGroupBox" name="breakFunctionGroupBox">
<property name="title">
<string>Break on functions:</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="breakCrtDbgReportCheckBox"/>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">

View File

@@ -200,6 +200,24 @@ bool CommonOptionsPage::matches(const QString &s) const
return m_searchKeywords.contains(s, Qt::CaseInsensitive); return m_searchKeywords.contains(s, Qt::CaseInsensitive);
} }
QString CommonOptionsPage::msgSetBreakpointAtFunction(const char *function)
{
return tr("Stop when %1() is called").arg(QLatin1String(function));
}
QString CommonOptionsPage::msgSetBreakpointAtFunctionToolTip(const char *function,
const QString &hint)
{
QString result = QLatin1String("<html><head/><body>");
result += tr("Always add a breakpoint on the <i>%1()</i> function.").arg(QLatin1String(function));
if (!hint.isEmpty()) {
result += QLatin1String("<br>");
result += hint;
}
result += QLatin1String("</body></html>");
return result;
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// LocalsAndExpressionsOptionsPage // LocalsAndExpressionsOptionsPage

View File

@@ -79,6 +79,10 @@ public:
void finish(); void finish();
bool matches(const QString &s) const; bool matches(const QString &s) const;
static QString msgSetBreakpointAtFunction(const char *function);
static QString msgSetBreakpointAtFunctionToolTip(const char *function,
const QString &hint = QString());
private: private:
const QSharedPointer<GlobalDebuggerOptions> m_options; const QSharedPointer<GlobalDebuggerOptions> m_options;
QSharedPointer<Utils::SavedActionSet> m_group; QSharedPointer<Utils::SavedActionSet> m_group;

View File

@@ -29,6 +29,7 @@
**************************************************************************/ **************************************************************************/
#include "gdboptionspage.h" #include "gdboptionspage.h"
#include "commonoptionspage.h"
#include "debuggeractions.h" #include "debuggeractions.h"
#include "debuggercore.h" #include "debuggercore.h"
#include "debuggerinternalconstants.h" #include "debuggerinternalconstants.h"
@@ -181,22 +182,16 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
"when starting GDB.</body></html>")); "when starting GDB.</body></html>"));
checkBoxBreakOnWarning = new QCheckBox(groupBoxGeneral); checkBoxBreakOnWarning = new QCheckBox(groupBoxGeneral);
checkBoxBreakOnWarning->setText(GdbOptionsPage::tr("Stop when qWarning() is called")); checkBoxBreakOnWarning->setText(CommonOptionsPage::msgSetBreakpointAtFunction("qWarning"));
checkBoxBreakOnWarning->setToolTip(GdbOptionsPage::tr( checkBoxBreakOnWarning->setToolTip(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip("qWarning"));
"<html><head/><body>Always add a breakpoint on the <i>qWarning()</i> function."
"</body></html>"));
checkBoxBreakOnFatal = new QCheckBox(groupBoxGeneral); checkBoxBreakOnFatal = new QCheckBox(groupBoxGeneral);
checkBoxBreakOnFatal->setText(GdbOptionsPage::tr("Stop when qFatal() is called")); checkBoxBreakOnFatal->setText(CommonOptionsPage::msgSetBreakpointAtFunction("qFatal"));
checkBoxBreakOnFatal->setToolTip(GdbOptionsPage::tr( checkBoxBreakOnFatal->setToolTip(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip("qFatal"));
"<html><head/><body>Always add a breakpoint on the <i>qFatal()</i> function."
"</body></html>"));
checkBoxBreakOnAbort = new QCheckBox(groupBoxGeneral); checkBoxBreakOnAbort = new QCheckBox(groupBoxGeneral);
checkBoxBreakOnAbort->setText(GdbOptionsPage::tr("Stop when abort() is called")); checkBoxBreakOnAbort->setText(CommonOptionsPage::msgSetBreakpointAtFunction("abort"));
checkBoxBreakOnAbort->setToolTip(GdbOptionsPage::tr( checkBoxBreakOnAbort->setText(CommonOptionsPage::msgSetBreakpointAtFunctionToolTip("abort"));
"<html><head/><body><p>Always add a breakpoint on the <i>abort()</i> function."
"</p></body></html>"));
checkBoxEnableReverseDebugging = new QCheckBox(groupBoxGeneral); checkBoxEnableReverseDebugging = new QCheckBox(groupBoxGeneral);
checkBoxEnableReverseDebugging->setText(GdbOptionsPage::tr("Enable reverse debugging")); checkBoxEnableReverseDebugging->setText(GdbOptionsPage::tr("Enable reverse debugging"));