Commit 8d6f67f5 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger: List break on catch/throw as such and map names in engine.

Introduce special setting 'Stop on exception' for CDB.
Reviewed-by: hjk
parent 2fff849a
......@@ -159,6 +159,9 @@ private:
//
//////////////////////////////////////////////////////////////////
const char *BreakpointData::throwFunction = "throw";
const char *BreakpointData::catchFunction = "catch";
BreakpointData::BreakpointData() :
m_handler(0), enabled(true),
pending(true), type(BreakpointType),
......
......@@ -66,6 +66,10 @@ public:
// This copies only the static data.
BreakpointData *clone() const;
// Generic name for function to break on 'throw'
static const char *throwFunction;
static const char *catchFunction;
private:
// Intentionally unimplemented.
// Making it copyable is tricky because of the markers.
......@@ -90,7 +94,9 @@ public:
int lineNumber; // Line in source file.
quint64 address; // Address for watchpoints.
QByteArray threadSpec; // Thread specification.
QString funcName; // Name of containing function.
// Name of containing function, special values:
// BreakpointData::throwFunction, BreakpointData::catchFunction
QString funcName;
bool useFullPath; // Should we use the full path when setting the bp?
// This is what gdb produced in response.
......
......@@ -334,9 +334,9 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
else if (act == addBreakpointAction)
addBreakpoint();
else if (act == breakAtThrowAction)
setModelData(RequestBreakByFunctionRole, "__cxa_throw");
setModelData(RequestBreakByFunctionRole, QLatin1String(BreakpointData::throwFunction));
else if (act == breakAtCatchAction)
setModelData(RequestBreakByFunctionRole, "__cxa_begin_catch");
setModelData(RequestBreakByFunctionRole, QLatin1String(BreakpointData::catchFunction));
}
void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
......
......@@ -53,7 +53,8 @@ CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::Break
}
rc.fileName = QDir::toNativeSeparators(bpd.fileName);
rc.condition = bpd.condition;
rc.funcName = bpd.funcName;
// Resolved function goes to bpd.bpFuncName.
rc.funcName = bpd.bpFuncName.isEmpty() ? bpd.funcName : bpd.bpFuncName;
rc.ignoreCount = bpd.ignoreCount;
rc.lineNumber = bpd.lineNumber;
rc.oneShot = false;
......@@ -92,7 +93,8 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl,
if (nbd->funcName.isEmpty()) {
breakPointOk = true;
} else {
switch (resolveSymbol(syms, &nbd->funcName, &warning)) {
nbd->bpFuncName = nbd->funcName;
switch (resolveSymbol(syms, &nbd->bpFuncName, &warning)) {
case ResolveSymbolOk:
breakPointOk = true;
break;
......@@ -128,7 +130,6 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl,
nbd->bpThreadSpec = nbd->threadSpec;
nbd->bpFileName = nbd->fileName;
nbd->bpLineNumber = nbd->lineNumber;
nbd->bpFuncName = nbd->funcName;
}
} // had symbol
if (!breakPointOk && !warning.isEmpty())
......
......@@ -409,7 +409,7 @@ void CdbEngine::setupEngine()
m_d->m_inferiorStartupComplete = false;
// Options
QString errorMessage;
if (!m_d->setBreakOnThrow(theDebuggerBoolSetting(BreakOnThrow), &errorMessage))
if (!m_d->setBreakOnThrow(m_d->m_options->breakOnException, &errorMessage))
showMessage(errorMessage, LogWarning);
m_d->setVerboseSymbolLoading(m_d->m_options->verboseSymbolLoading);
// Figure out dumper. @TODO: same in gdb...
......
......@@ -30,6 +30,7 @@
#include "cdbmodules.h"
#include "moduleshandler.h"
#include "cdbengine_p.h"
#include "breakpoint.h"
#include <QtCore/QFileInfo>
#include <QtCore/QRegExp>
......@@ -180,14 +181,35 @@ static ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol,
// Is it an incomplete symbol?
if (symbol->contains(QLatin1Char('!')))
return ResolveSymbolOk;
// 'main' is a #define for gdb, but not for VS
if (*symbol == QLatin1String("qMain"))
// Throw and catch
bool withinMSVCRunTime = false;
if (*symbol == QLatin1String(BreakpointData::throwFunction)) {
*symbol = QLatin1String("CxxThrowException");
withinMSVCRunTime = true;
} else if (*symbol == QLatin1String(BreakpointData::catchFunction)) {
*symbol = QLatin1String("__CxxCallCatchBlock");
withinMSVCRunTime = true;
} else if (*symbol == QLatin1String("qMain")) // 'main' is a #define for gdb, but not for VS
*symbol = QLatin1String("main");
// resolve
if (!searchSymbols(syms, *symbol, matches, errorMessage))
return ResolveSymbolError;
if (matches->empty())
// Exception functions sometimes show up ambiguously as'QtGuid4!CxxThrowException',
// 'MSVCR100D!CxxThrowException', QtCored4!CxxThrowException',
// 'MSVCP100D!CxxThrowException' and 'msvcrt!CxxThrowException',
// 'OLEAUT32!CxxThrowException'...restrict to MSVC-RunTime (any MSVC version).
if (withinMSVCRunTime && matches->size() > 1) {
for (QStringList::iterator it = matches->begin(); it != matches->end(); )
if (it->startsWith(QLatin1String("MSVCR"))) {
++it;
} else {
it = matches->erase(it);
}
}
if (matches->empty()) {
*errorMessage = QString::fromLatin1("No match for '%1' found").arg(*symbol);
return ResolveSymbolNotFound;
}
*symbol = matches->front();
if (matches->size() > 1) {
*errorMessage = QString::fromLatin1("Ambiguous symbol '%1': %2").
......
......@@ -39,6 +39,7 @@ static const char *enabledKeyC = "Enabled";
static const char *pathKeyC = "Path";
static const char *symbolPathsKeyC = "SymbolPaths";
static const char *sourcePathsKeyC = "SourcePaths";
static const char *breakOnExceptionKeyC = "BreakOnException";
static const char *verboseSymbolLoadingKeyC = "VerboseSymbolLoading";
static const char *fastLoadDebuggingHelpersKeyC = "FastLoadDebuggingHelpers";
......@@ -47,6 +48,7 @@ namespace Internal {
CdbOptions::CdbOptions() :
enabled(false),
breakOnException(false),
verboseSymbolLoading(false),
fastLoadDebuggingHelpers(true)
{
......@@ -83,6 +85,7 @@ void CdbOptions::fromSettings(const QSettings *s)
sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList();
verboseSymbolLoading = s->value(keyRoot + QLatin1String(verboseSymbolLoadingKeyC), false).toBool();
fastLoadDebuggingHelpers = s->value(keyRoot + QLatin1String(fastLoadDebuggingHelpersKeyC), true).toBool();
breakOnException = s->value(keyRoot + QLatin1String(breakOnExceptionKeyC), false).toBool();
}
void CdbOptions::toSettings(QSettings *s) const
......@@ -94,6 +97,7 @@ void CdbOptions::toSettings(QSettings *s) const
s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths);
s->setValue(QLatin1String(verboseSymbolLoadingKeyC), verboseSymbolLoading);
s->setValue(QLatin1String(fastLoadDebuggingHelpersKeyC), fastLoadDebuggingHelpers);
s->setValue(QLatin1String(breakOnExceptionKeyC), breakOnException);
s->endGroup();
}
......@@ -108,6 +112,8 @@ unsigned CdbOptions::compare(const CdbOptions &rhs) const
rc |= SymbolOptionsChanged;
if (fastLoadDebuggingHelpers != rhs.fastLoadDebuggingHelpers)
rc |= FastLoadDebuggingHelpersChanged;
if (breakOnException != rhs.breakOnException)
rc |= OtherOptionsChanged;
return rc;
}
......
......@@ -52,7 +52,9 @@ public:
enum ChangeFlags { InitializationOptionsChanged = 0x1,
DebuggerPathsChanged = 0x2,
SymbolOptionsChanged = 0x4,
FastLoadDebuggingHelpersChanged = 0x8 };
FastLoadDebuggingHelpersChanged = 0x8,
OtherOptionsChanged = 0x100
};
unsigned compare(const CdbOptions &s) const;
// Format a symbol server specification with a cache directory
......@@ -67,6 +69,7 @@ public:
QString path;
QStringList symbolPaths;
QStringList sourcePaths;
bool breakOnException;
bool verboseSymbolLoading;
bool fastLoadDebuggingHelpers;
};
......
......@@ -86,6 +86,7 @@ void CdbOptionsPageWidget::setOptions(CdbOptions &o)
m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
m_ui.verboseSymbolLoadingCheckBox->setChecked(o.verboseSymbolLoading);
m_ui.fastLoadDebuggingHelpersCheckBox->setChecked(o.fastLoadDebuggingHelpers);
m_ui.breakOnExceptionCheckBox->setChecked(o.breakOnException);
}
CdbOptions CdbOptionsPageWidget::options() const
......@@ -97,6 +98,7 @@ CdbOptions CdbOptionsPageWidget::options() const
rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
rc.verboseSymbolLoading = m_ui.verboseSymbolLoadingCheckBox->isChecked();
rc.fastLoadDebuggingHelpers = m_ui.fastLoadDebuggingHelpersCheckBox->isChecked();
rc.breakOnException = m_ui.breakOnExceptionCheckBox->isChecked();
return rc;
}
......@@ -134,7 +136,8 @@ QString CdbOptionsPageWidget::searchKeywords() const
QTextStream(&rc) << m_ui.pathLabel->text() << ' ' << m_ui.symbolPathLabel->text()
<< ' ' << m_ui.sourcePathLabel->text()
<< ' ' << m_ui.verboseSymbolLoadingCheckBox->text()
<< ' ' << m_ui.fastLoadDebuggingHelpersCheckBox->text();
<< ' ' << m_ui.fastLoadDebuggingHelpersCheckBox->text()
<< ' ' << m_ui.breakOnExceptionCheckBox->text();
rc.remove(QLatin1Char('&'));
return rc;
}
......
......@@ -88,20 +88,27 @@
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0" colspan="2">
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="verboseSymbolLoadingCheckBox">
<property name="text">
<string>Verbose symbol loading</string>
</property>
</widget>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QCheckBox" name="fastLoadDebuggingHelpersCheckBox">
<property name="text">
<string>Fast loading of debugging helpers</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="breakOnExceptionCheckBox">
<property name="text">
<string>Break on exception</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
......
......@@ -192,6 +192,9 @@ bool BreakPoint::apply(CIDebugBreakpoint *ibp, QString *errorMessage) const
*errorMessage = msgCannotSetBreakpoint(expr, msg);
return false;
}
hr = ibp->GetFlags(&flags);
if (SUCCEEDED(hr))
qDebug("BP %s Flags %x", qPrintable(expr), flags);
return true;
}
......
......@@ -2144,8 +2144,13 @@ static inline QByteArray bpAddressSpec(quint64 address)
QByteArray GdbEngine::breakpointLocation(const BreakpointData *data)
{
if (!data->funcName.isEmpty())
if (!data->funcName.isEmpty()) {
if (data->funcName == QLatin1String(BreakpointData::throwFunction))
return QByteArray("__cxa_throw");
if (data->funcName == QLatin1String(BreakpointData::catchFunction))
return QByteArray("__cxa_begin_catch");
return data->funcName.toLatin1();
}
if (data->address)
return bpAddressSpec(data->address);
// In this case, data->funcName is something like '*0xdeadbeef'
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment