forked from qt-creator/qt-creator
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:
@@ -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()) {
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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">
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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"));
|
||||||
|
Reference in New Issue
Block a user