diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp
index a88b7e9e4e9..12de1c163e2 100644
--- a/src/plugins/debugger/cdb/cdbengine.cpp
+++ b/src/plugins/debugger/cdb/cdbengine.cpp
@@ -775,12 +775,59 @@ void CdbEngine::setupInferior()
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()
{
if (debug)
qDebug("runEngine");
foreach (const QString &breakEvent, m_options->breakEvents)
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) {
QTC_ASSERT(!m_coreStopReason.isNull(), return; );
notifyInferiorUnrunnable();
@@ -2990,6 +3037,8 @@ void CdbEngine::handleBreakPoints(const GdbMi &value)
qPrintable(reportedResponse.toString()));
if (reportedResponse.id.isValid() && !reportedResponse.pending) {
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);
const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(mid);
if (it != m_pendingBreakpointMap.end()) {
diff --git a/src/plugins/debugger/cdb/cdboptions.cpp b/src/plugins/debugger/cdb/cdboptions.cpp
index 413b2763c84..1c629da9411 100644
--- a/src/plugins/debugger/cdb/cdboptions.cpp
+++ b/src/plugins/debugger/cdb/cdboptions.cpp
@@ -36,6 +36,7 @@ static const char settingsGroupC[] = "CDB2";
static const char symbolPathsKeyC[] = "SymbolPaths";
static const char sourcePathsKeyC[] = "SourcePaths";
static const char breakEventKeyC[] = "BreakEvent";
+static const char breakFunctionsKeyC[] = "BreakFunctions";
static const char additionalArgumentsKeyC[] = "AdditionalArguments";
static const char cdbConsoleKeyC[] = "CDB_Console";
static const char breakpointCorrectionKeyC[] = "BreakpointCorrection";
@@ -43,6 +44,8 @@ static const char breakpointCorrectionKeyC[] = "BreakpointCorrection";
namespace Debugger {
namespace Internal {
+const char *CdbOptions::crtDbgReport = "CrtDbgReport";
+
CdbOptions::CdbOptions() : cdbConsole(false), breakpointCorrection(true)
{
}
@@ -57,6 +60,8 @@ void CdbOptions::clear()
symbolPaths.clear();
sourcePaths.clear();
cdbConsole = false;
+ breakEvents.clear();
+ breakFunctions.clear();
}
QStringList CdbOptions::oldEngineSymbolPaths(const QSettings *s)
@@ -72,6 +77,7 @@ void CdbOptions::fromSettings(QSettings *s)
symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList();
sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), 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();
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(sourcePathsKeyC), sourcePaths);
s->setValue(QLatin1String(breakEventKeyC), breakEvents);
+ s->setValue(QLatin1String(breakFunctionsKeyC), breakFunctions);
s->setValue(QLatin1String(additionalArgumentsKeyC), additionalArguments);
s->setValue(QLatin1String(cdbConsoleKeyC), QVariant(cdbConsole));
s->setValue(QLatin1String(breakpointCorrectionKeyC), QVariant(breakpointCorrection));
@@ -95,7 +102,8 @@ bool CdbOptions::equals(const CdbOptions &rhs) const
&& additionalArguments == rhs.additionalArguments
&& symbolPaths == rhs.symbolPaths
&& sourcePaths == rhs.sourcePaths
- && breakEvents == rhs.breakEvents;
+ && breakEvents == rhs.breakEvents
+ && breakFunctions == rhs.breakFunctions;
}
} // namespace Internal
diff --git a/src/plugins/debugger/cdb/cdboptions.h b/src/plugins/debugger/cdb/cdboptions.h
index 7e29a3eb05e..f681c5e9f0f 100644
--- a/src/plugins/debugger/cdb/cdboptions.h
+++ b/src/plugins/debugger/cdb/cdboptions.h
@@ -62,10 +62,13 @@ public:
QStringList sourcePaths;
// Events to break on (Command 'sxe' with abbreviation and optional parameter)
QStringList breakEvents;
+ QStringList breakFunctions;
// Launch CDB's own console instead of Qt Creator's
bool cdbConsole;
// Perform code-model based correction of breakpoint location.
bool breakpointCorrection;
+
+ static const char *crtDbgReport;
};
inline bool operator==(const CdbOptions &s1, const CdbOptions &s2)
diff --git a/src/plugins/debugger/cdb/cdboptionspage.cpp b/src/plugins/debugger/cdb/cdboptionspage.cpp
index a8b09f35fc8..2ee23b4c119 100644
--- a/src/plugins/debugger/cdb/cdboptionspage.cpp
+++ b/src/plugins/debugger/cdb/cdboptionspage.cpp
@@ -30,6 +30,7 @@
#include "cdboptionspage.h"
#include "cdboptions.h"
+#include "commonoptionspage.h"
#include "debuggerinternalconstants.h"
#include "cdbengine.h"
@@ -176,6 +177,11 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
eventLayout->setContentsMargins(margins);
eventLayout->addWidget(m_breakEventWidget);
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)
@@ -186,6 +192,7 @@ void CdbOptionsPageWidget::setOptions(CdbOptions &o)
m_breakEventWidget->setBreakEvents(o.breakEvents);
m_ui.consoleCheckBox->setChecked(o.cdbConsole);
m_ui.breakpointCorrectionCheckBox->setChecked(o.breakpointCorrection);
+ m_ui.breakCrtDbgReportCheckBox->setChecked(o.breakFunctions.contains(QLatin1String(CdbOptions::crtDbgReport)));
}
CdbOptions CdbOptionsPageWidget::options() const
@@ -197,6 +204,8 @@ CdbOptions CdbOptionsPageWidget::options() const
rc.breakEvents = m_breakEventWidget->breakEvents();
rc.cdbConsole = m_ui.consoleCheckBox->isChecked();
rc.breakpointCorrection = m_ui.breakpointCorrectionCheckBox->isChecked();
+ if (m_ui.breakCrtDbgReportCheckBox->isChecked())
+ rc.breakFunctions.push_back(QLatin1String(CdbOptions::crtDbgReport));
return rc;
}
diff --git a/src/plugins/debugger/cdb/cdboptionspagewidget.ui b/src/plugins/debugger/cdb/cdboptionspagewidget.ui
index 8160cd74db3..41b3d6a1ffb 100644
--- a/src/plugins/debugger/cdb/cdboptionspagewidget.ui
+++ b/src/plugins/debugger/cdb/cdboptionspagewidget.ui
@@ -120,6 +120,18 @@
+ -
+
+
+ Break on functions:
+
+
+
-
+
+
+
+
+
-
diff --git a/src/plugins/debugger/commonoptionspage.cpp b/src/plugins/debugger/commonoptionspage.cpp
index 495f28af0fb..06a74b5235b 100644
--- a/src/plugins/debugger/commonoptionspage.cpp
+++ b/src/plugins/debugger/commonoptionspage.cpp
@@ -200,6 +200,24 @@ bool CommonOptionsPage::matches(const QString &s) const
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("");
+ result += tr("Always add a breakpoint on the %1() function.").arg(QLatin1String(function));
+ if (!hint.isEmpty()) {
+ result += QLatin1String("
");
+ result += hint;
+ }
+ result += QLatin1String("");
+ return result;
+}
+
///////////////////////////////////////////////////////////////////////
//
// LocalsAndExpressionsOptionsPage
diff --git a/src/plugins/debugger/commonoptionspage.h b/src/plugins/debugger/commonoptionspage.h
index b5eaf9392a5..4f5b76ab2c0 100644
--- a/src/plugins/debugger/commonoptionspage.h
+++ b/src/plugins/debugger/commonoptionspage.h
@@ -79,6 +79,10 @@ public:
void finish();
bool matches(const QString &s) const;
+ static QString msgSetBreakpointAtFunction(const char *function);
+ static QString msgSetBreakpointAtFunctionToolTip(const char *function,
+ const QString &hint = QString());
+
private:
const QSharedPointer m_options;
QSharedPointer m_group;
diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp
index 5f3bc80efa4..4d11152141e 100644
--- a/src/plugins/debugger/gdb/gdboptionspage.cpp
+++ b/src/plugins/debugger/gdb/gdboptionspage.cpp
@@ -29,6 +29,7 @@
**************************************************************************/
#include "gdboptionspage.h"
+#include "commonoptionspage.h"
#include "debuggeractions.h"
#include "debuggercore.h"
#include "debuggerinternalconstants.h"
@@ -181,22 +182,16 @@ GdbOptionsPageWidget::GdbOptionsPageWidget(QWidget *parent)
"when starting GDB.