forked from qt-creator/qt-creator
Debugger: Handle throw/catch/main as BreakpointType enum values.
Remove BreakHandler::hasPendingBreakpoints, handle new types in CDB and gdb. Start fixing Breakpoint-Dialog. Add assignment of Breakpointresponse from BreakpointParameters. Reviewed-by: hjk
This commit is contained in:
@@ -74,16 +74,6 @@ int BreakHandler::rowCount(const QModelIndex &parent) const
|
||||
return parent.isValid() ? 0 : m_storage.size();
|
||||
}
|
||||
|
||||
// FIXME: Only used by cdb. Move there?
|
||||
bool BreakHandler::hasPendingBreakpoints() const
|
||||
{
|
||||
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
|
||||
for ( ; it != et; ++it)
|
||||
if (it->isPending())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool fileNameMatch(const QString &f1, const QString &f2)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -907,11 +897,21 @@ QString BreakHandler::BreakpointItem::toToolTip() const
|
||||
case BreakpointByAddress:
|
||||
t = tr("Breakpoint by Address");
|
||||
break;
|
||||
case BreakpointAtThrow:
|
||||
t = tr("Breakpoint at \"throw\"");
|
||||
break;
|
||||
case BreakpointAtCatch:
|
||||
t = tr("Breakpoint at \"catch\"");
|
||||
break;
|
||||
case BreakpointAtMain:
|
||||
t = tr("Breakpoint at Function \"main()\"");
|
||||
break;
|
||||
case Watchpoint:
|
||||
t = tr("Watchpoint");
|
||||
break;
|
||||
case UnknownType:
|
||||
t = tr("Unknown Breakpoint Type");
|
||||
break;
|
||||
}
|
||||
|
||||
QString rc;
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const;
|
||||
BreakpointIds unclaimedBreakpointIds() const;
|
||||
int size() const { return m_storage.size(); }
|
||||
bool hasPendingBreakpoints() const;
|
||||
|
||||
// Find a breakpoint matching approximately the data in needle.
|
||||
BreakpointId findSimilarBreakpoint(const BreakpointResponse &needle) const;
|
||||
|
||||
@@ -41,9 +41,6 @@ namespace Internal {
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *BreakpointData::throwFunction = "throw";
|
||||
const char *BreakpointData::catchFunction = "catch";
|
||||
|
||||
BreakpointParameters::BreakpointParameters(BreakpointType t) :
|
||||
type(t), enabled(true), useFullPath(false),
|
||||
ignoreCount(0), lineNumber(0), address(0)
|
||||
@@ -52,7 +49,7 @@ BreakpointParameters::BreakpointParameters(BreakpointType t) :
|
||||
|
||||
bool BreakpointParameters::equals(const BreakpointParameters &rhs) const
|
||||
{
|
||||
return type != rhs.type && enabled == rhs.enabled
|
||||
return type == rhs.type && enabled == rhs.enabled
|
||||
&& useFullPath == rhs.useFullPath
|
||||
&& fileName == rhs.fileName && condition == rhs.condition
|
||||
&& ignoreCount == rhs.ignoreCount && lineNumber == rhs.lineNumber
|
||||
@@ -168,5 +165,14 @@ QString BreakpointResponse::toString() const
|
||||
return result;
|
||||
}
|
||||
|
||||
void BreakpointResponse::fromParameters(const BreakpointParameters &p)
|
||||
{
|
||||
BreakpointParameters::operator=(p);
|
||||
number = 0;
|
||||
fullName.clear();
|
||||
multiple = false;
|
||||
state.clear();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -62,8 +62,9 @@ enum BreakpointType
|
||||
BreakpointByFileAndLine,
|
||||
BreakpointByFunction,
|
||||
BreakpointByAddress,
|
||||
//BreakpointAtThrow, // FIXME: actually use this
|
||||
//BreakpointAtCatch, // FIXME: actually use this
|
||||
BreakpointAtThrow,
|
||||
BreakpointAtCatch,
|
||||
BreakpointAtMain,
|
||||
Watchpoint,
|
||||
};
|
||||
|
||||
@@ -135,9 +136,6 @@ public:
|
||||
|
||||
bool isWatchpoint() const { return type() == Watchpoint; }
|
||||
bool isBreakpoint() const { return type() != Watchpoint; } // Enough for now.
|
||||
// Generic name for function to break on 'throw'
|
||||
static const char *throwFunction;
|
||||
static const char *catchFunction;
|
||||
|
||||
private:
|
||||
// All setters return true on change.
|
||||
@@ -173,6 +171,8 @@ public:
|
||||
QString toString() const;
|
||||
|
||||
public:
|
||||
void fromParameters(const BreakpointParameters &p);
|
||||
|
||||
int number; // Breakpoint number assigned by the debugger engine.
|
||||
QString fullName; // Full file name acknowledged by the debugger engine.
|
||||
bool multiple; // Happens in constructors/gdb.
|
||||
|
||||
@@ -69,72 +69,83 @@ public:
|
||||
explicit BreakpointDialog(QWidget *parent);
|
||||
bool showDialog(BreakpointData *data);
|
||||
|
||||
void setParameters(const BreakpointParameters &p);
|
||||
BreakpointParameters parameters() const;
|
||||
|
||||
public slots:
|
||||
void typeChanged(int index);
|
||||
|
||||
private:
|
||||
void setType(BreakpointType type);
|
||||
BreakpointType type() const;
|
||||
};
|
||||
|
||||
BreakpointDialog::BreakpointDialog(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
// match BreakpointType (except unknown type) with additional item
|
||||
setupUi(this);
|
||||
comboBoxType->insertItem(0, tr("File and Line Number"));
|
||||
comboBoxType->insertItem(1, tr("Function Name"));
|
||||
comboBoxType->insertItem(2, tr("Function \"main()\""));
|
||||
comboBoxType->insertItem(3, tr("Address"));
|
||||
QStringList types;
|
||||
types << tr("File and Line Number") << tr("Function Name") << tr("Address")
|
||||
<< tr("throw") << tr("catch") << tr("Function \"main()\"")
|
||||
<< tr("Address (Watchpoint)");
|
||||
QTC_ASSERT(types.size() == Watchpoint, return; )
|
||||
comboBoxType->addItems(types);
|
||||
pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
|
||||
connect(comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int)));
|
||||
lineEditIgnoreCount->setValidator(
|
||||
new QIntValidator(0, 2147483647, lineEditIgnoreCount));
|
||||
}
|
||||
|
||||
bool BreakpointDialog::showDialog(BreakpointData *data)
|
||||
void BreakpointDialog::setType(BreakpointType type)
|
||||
{
|
||||
pathChooserFileName->setPath(data->fileName());
|
||||
lineEditLineNumber->setText(QString::number(data->lineNumber()));
|
||||
lineEditFunction->setText(data->functionName());
|
||||
lineEditCondition->setText(QString::fromUtf8(data->condition()));
|
||||
lineEditIgnoreCount->setText(QString::number(data->ignoreCount()));
|
||||
checkBoxUseFullPath->setChecked(data->useFullPath());
|
||||
lineEditThreadSpec->setText(QString::fromUtf8(data->threadSpec()));
|
||||
const quint64 address = data->address();
|
||||
if (address)
|
||||
lineEditAddress->setText(QString::fromAscii("0x%1").arg(address, 0, 16));
|
||||
int initialType = 0;
|
||||
if (!data->functionName().isEmpty())
|
||||
initialType = data->functionName() == QLatin1String("main") ? 2 : 1;
|
||||
if (address)
|
||||
initialType = 3;
|
||||
typeChanged(initialType);
|
||||
|
||||
if (exec() != QDialog::Accepted)
|
||||
return false;
|
||||
|
||||
// Check if changed.
|
||||
const int newLineNumber = lineEditLineNumber->text().toInt();
|
||||
const bool newUseFullPath = checkBoxUseFullPath->isChecked();
|
||||
const quint64 newAddress = lineEditAddress->text().toULongLong(0, 0);
|
||||
const QString newFunction = lineEditFunction->text();
|
||||
const QString newFileName = pathChooserFileName->path();
|
||||
const QByteArray newCondition = lineEditCondition->text().toUtf8();
|
||||
const int newIgnoreCount = lineEditIgnoreCount->text().toInt();
|
||||
const QByteArray newThreadSpec = lineEditThreadSpec->text().toUtf8();
|
||||
|
||||
bool result = false;
|
||||
result |= data->setAddress(newAddress);
|
||||
result |= data->setFunctionName(newFunction);
|
||||
result |= data->setUseFullPath(newUseFullPath);
|
||||
result |= data->setFileName(newFileName);
|
||||
result |= data->setLineNumber(newLineNumber);
|
||||
result |= data->setCondition(newCondition);
|
||||
result |= data->setIgnoreCount(newIgnoreCount);
|
||||
result |= data->setThreadSpec(newThreadSpec);
|
||||
return result;
|
||||
const int comboIndex = type - 1; // Skip UnknownType
|
||||
if (comboIndex != comboBoxType->currentIndex()) {
|
||||
comboBoxType->setCurrentIndex(comboIndex);
|
||||
typeChanged(comboIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpointDialog::typeChanged(int index)
|
||||
BreakpointType BreakpointDialog::type() const
|
||||
{
|
||||
const bool isLineVisible = index == 0;
|
||||
const bool isFunctionVisible = index == 1;
|
||||
const bool isAddressVisible = index == 3;
|
||||
const int type = comboBoxType->currentIndex() + 1; // Skip unknown type
|
||||
return static_cast<BreakpointType>(type);
|
||||
}
|
||||
|
||||
void BreakpointDialog::setParameters(const BreakpointParameters &p)
|
||||
{
|
||||
pathChooserFileName->setPath(p.fileName);
|
||||
lineEditLineNumber->setText(QString::number(p.lineNumber));
|
||||
lineEditFunction->setText(p.functionName);
|
||||
lineEditCondition->setText(QString::fromUtf8(p.condition));
|
||||
lineEditIgnoreCount->setText(QString::number(p.ignoreCount));
|
||||
checkBoxUseFullPath->setChecked(p.useFullPath);
|
||||
lineEditThreadSpec->setText(p.threadSpec);
|
||||
const quint64 address = p.address;
|
||||
if (address)
|
||||
lineEditAddress->setText(QString::fromAscii("0x%1").arg(address, 0, 16));
|
||||
setType(p.type);
|
||||
}
|
||||
|
||||
BreakpointParameters BreakpointDialog::parameters() const
|
||||
{
|
||||
BreakpointParameters rc(type());
|
||||
rc.lineNumber = lineEditLineNumber->text().toInt();
|
||||
rc.useFullPath = checkBoxUseFullPath->isChecked();
|
||||
rc.address = lineEditAddress->text().toULongLong(0, 0);
|
||||
rc.functionName = lineEditFunction->text();
|
||||
rc.fileName = pathChooserFileName->path();
|
||||
rc.condition = lineEditCondition->text().toUtf8();
|
||||
rc.ignoreCount = lineEditIgnoreCount->text().toInt();
|
||||
rc.threadSpec = lineEditThreadSpec->text().toUtf8();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void BreakpointDialog::typeChanged(int)
|
||||
{
|
||||
const BreakpointType t = type();
|
||||
const bool isLineVisible = t == BreakpointByFileAndLine;
|
||||
const bool isFunctionVisible = t == BreakpointByFunction || t == BreakpointAtMain;
|
||||
const bool isAddressVisible = t == BreakpointByAddress || t == Watchpoint;
|
||||
labelFileName->setEnabled(isLineVisible);
|
||||
pathChooserFileName->setEnabled(isLineVisible);
|
||||
labelLineNumber->setEnabled(isLineVisible);
|
||||
@@ -145,10 +156,34 @@ void BreakpointDialog::typeChanged(int index)
|
||||
lineEditFunction->setEnabled(isFunctionVisible);
|
||||
labelAddress->setEnabled(isAddressVisible);
|
||||
lineEditAddress->setEnabled(isAddressVisible);
|
||||
if (index == 2)
|
||||
if (t == BreakpointAtMain)
|
||||
lineEditFunction->setText(QLatin1String("main"));
|
||||
}
|
||||
|
||||
bool BreakpointDialog::showDialog(BreakpointData *data)
|
||||
{
|
||||
setParameters(data->parameters());
|
||||
if (exec() != QDialog::Accepted)
|
||||
return false;
|
||||
|
||||
// Check if changed.
|
||||
const BreakpointParameters newParameters = parameters();
|
||||
if (newParameters == data->parameters())
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
result |= data->setType(newParameters.type);
|
||||
result |= data->setAddress(newParameters.address);
|
||||
result |= data->setFunctionName(newParameters.functionName);
|
||||
result |= data->setUseFullPath(newParameters.useFullPath);
|
||||
result |= data->setFileName(newParameters.fileName);
|
||||
result |= data->setLineNumber(newParameters.lineNumber);
|
||||
result |= data->setCondition(newParameters.condition);
|
||||
result |= data->setIgnoreCount(newParameters.ignoreCount);
|
||||
result |= data->setThreadSpec(newParameters.threadSpec);
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakWindow
|
||||
@@ -292,7 +327,6 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
synchronizeAction->setEnabled(debuggerCore()->hasSnapshots());
|
||||
|
||||
QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
|
||||
QModelIndex idx2 = idx0.sibling(idx0.row(), 2);
|
||||
const BreakpointId id = handler->findBreakpointByIndex(idx0);
|
||||
|
||||
bool enabled = si.isEmpty() || handler->isEnabled(id);
|
||||
@@ -363,14 +397,9 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
else if (act == addBreakpointAction)
|
||||
addBreakpoint();
|
||||
else if (act == breakAtThrowAction) {
|
||||
BreakpointData data(BreakpointByFunction);
|
||||
data.setFunctionName(BreakpointData::throwFunction);
|
||||
handler->appendBreakpoint(data);
|
||||
handler->appendBreakpoint(BreakpointData(BreakpointAtThrow));
|
||||
} else if (act == breakAtCatchAction) {
|
||||
// FIXME: Use the proper breakpoint type instead.
|
||||
BreakpointData data(BreakpointByFunction);
|
||||
data.setFunctionName(BreakpointData::catchFunction);
|
||||
handler->appendBreakpoint(data);
|
||||
handler->appendBreakpoint(BreakpointData(BreakpointAtCatch));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,27 +40,27 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
// Convert breakpoint structs
|
||||
static CdbCore::BreakPoint breakPointFromBreakPointData(const BreakpointData &bpd, const QString &functionName)
|
||||
static CdbCore::BreakPoint breakPointFromBreakPointData(const BreakpointParameters &bpd, const QString &functionName)
|
||||
{
|
||||
CdbCore::BreakPoint rc;
|
||||
rc.type = bpd.type() == Watchpoint ?
|
||||
rc.type = bpd.type == Watchpoint ?
|
||||
CdbCore::BreakPoint::Data :
|
||||
CdbCore::BreakPoint::Code ;
|
||||
|
||||
rc.address = bpd.address();
|
||||
if (!bpd.threadSpec().isEmpty()) {
|
||||
rc.address = bpd.address;
|
||||
if (!bpd.threadSpec.isEmpty()) {
|
||||
bool ok;
|
||||
rc.threadId = bpd.threadSpec().toInt(&ok);
|
||||
rc.threadId = bpd.threadSpec.toInt(&ok);
|
||||
if (!ok)
|
||||
qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.threadSpec().constData());
|
||||
qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.threadSpec.constData());
|
||||
}
|
||||
rc.fileName = QDir::toNativeSeparators(bpd.fileName());
|
||||
rc.condition = bpd.condition();
|
||||
rc.funcName = functionName.isEmpty() ? bpd.functionName() : functionName;
|
||||
rc.ignoreCount = bpd.ignoreCount();
|
||||
rc.lineNumber = bpd.lineNumber();
|
||||
rc.fileName = QDir::toNativeSeparators(bpd.fileName);
|
||||
rc.condition = bpd.condition;
|
||||
rc.funcName = functionName.isEmpty() ? bpd.functionName : functionName;
|
||||
rc.ignoreCount = bpd.ignoreCount;
|
||||
rc.lineNumber = bpd.lineNumber;
|
||||
rc.oneShot = false;
|
||||
rc.enabled = bpd.isEnabled();
|
||||
rc.enabled = bpd.enabled;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -69,31 +69,38 @@ static inline QString msgCannotSetBreakAtFunction(const QString &func, const QSt
|
||||
return QString::fromLatin1("Cannot set a breakpoint at '%1': %2").arg(func, why);
|
||||
}
|
||||
|
||||
void setBreakpointResponse(const BreakpointData *nbd, int number, BreakpointResponse *response)
|
||||
static inline BreakpointParameters transformBreakpoint(const BreakpointParameters &p)
|
||||
{
|
||||
response->address = nbd->address();
|
||||
response->number = number;
|
||||
response->functionName = nbd->functionName();
|
||||
response->type = nbd->type();
|
||||
response->condition = nbd->condition();
|
||||
response->ignoreCount = nbd->ignoreCount();
|
||||
response->fullName = response->fileName = nbd->fileName();
|
||||
response->lineNumber = nbd->lineNumber();
|
||||
response->threadSpec = nbd->threadSpec();
|
||||
response->enabled = nbd->isEnabled();
|
||||
if (p.type == BreakpointAtThrow) {
|
||||
BreakpointParameters rc(BreakpointByFunction);
|
||||
rc.functionName = QLatin1String(cdbThrowFunction);
|
||||
return rc;
|
||||
}
|
||||
if (p.type == BreakpointAtCatch) {
|
||||
BreakpointParameters rc(BreakpointByFunction);
|
||||
rc.functionName = QLatin1String(cdbCatchFunction);
|
||||
return rc;
|
||||
}
|
||||
if (p.type == BreakpointAtMain) {
|
||||
BreakpointParameters rc(BreakpointByFunction);
|
||||
rc.functionName = QLatin1String("main");
|
||||
return rc;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
bool addCdbBreakpoint(CIDebugControl* debugControl,
|
||||
CIDebugSymbols *syms,
|
||||
const BreakpointData *nbd,
|
||||
const BreakpointParameters &bpIn,
|
||||
BreakpointResponse *response,
|
||||
QString *errorMessage)
|
||||
{
|
||||
const BreakpointParameters bp = transformBreakpoint(bpIn);
|
||||
errorMessage->clear();
|
||||
// Function breakpoints: Are the module names specified?
|
||||
QString resolvedFunction;
|
||||
if (nbd->type() == BreakpointByFunction) {
|
||||
resolvedFunction = nbd->functionName();
|
||||
if (bp.type == BreakpointByFunction) {
|
||||
resolvedFunction = bp.functionName;
|
||||
switch (resolveSymbol(syms, &resolvedFunction, errorMessage)) {
|
||||
case ResolveSymbolOk:
|
||||
break;
|
||||
@@ -101,21 +108,23 @@ bool addCdbBreakpoint(CIDebugControl* debugControl,
|
||||
break;
|
||||
case ResolveSymbolNotFound:
|
||||
case ResolveSymbolError:
|
||||
*errorMessage = msgCannotSetBreakAtFunction(nbd->functionName(), *errorMessage);
|
||||
*errorMessage = msgCannotSetBreakAtFunction(bp.functionName, *errorMessage);
|
||||
return false;
|
||||
}
|
||||
if (debugBreakpoints)
|
||||
qDebug() << nbd->functionName() << " resolved to " << resolvedFunction;
|
||||
qDebug() << bp.functionName << " resolved to " << resolvedFunction;
|
||||
} // function breakpoint
|
||||
// Now add...
|
||||
quint64 address;
|
||||
unsigned long id;
|
||||
const CdbCore::BreakPoint ncdbbp = breakPointFromBreakPointData(*nbd, resolvedFunction);
|
||||
const CdbCore::BreakPoint ncdbbp = breakPointFromBreakPointData(bp, resolvedFunction);
|
||||
if (!ncdbbp.add(debugControl, errorMessage, &id, &address))
|
||||
return false;
|
||||
if (debugBreakpoints)
|
||||
qDebug("Added %lu at 0x%lx %s", id, address, qPrintable(ncdbbp.toString()));
|
||||
setBreakpointResponse(nbd, id, response);
|
||||
|
||||
response->fromParameters(bp);
|
||||
response->number = id;
|
||||
response->address = address;
|
||||
response->functionName = resolvedFunction;
|
||||
return true;
|
||||
|
||||
@@ -40,13 +40,13 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
class BreakpointData;
|
||||
class BreakpointParameters;
|
||||
class BreakpointResponse;
|
||||
|
||||
// Convert breakpoint structs
|
||||
bool addCdbBreakpoint(CIDebugControl* debugControl,
|
||||
CIDebugSymbols *syms,
|
||||
const BreakpointData *nbd,
|
||||
const BreakpointParameters &bp,
|
||||
BreakpointResponse *response,
|
||||
QString *errorMessage);
|
||||
|
||||
@@ -54,9 +54,6 @@ bool deleteCdbBreakpoints(CIDebugControl* debugControl, QString *errorMessage);
|
||||
|
||||
void debugCdbBreakpoints(CIDebugControl* debugControl);
|
||||
|
||||
// Set response from data.
|
||||
void setBreakpointResponse(const BreakpointData *nbd, int number, BreakpointResponse *response);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
@@ -531,11 +531,7 @@ void CdbEnginePrivate::processCreatedAttached(ULONG64 processHandle, ULONG64 ini
|
||||
}
|
||||
// Clear any saved breakpoints and set initial breakpoints
|
||||
m_engine->executeDebuggerCommand(QLatin1String("bc"));
|
||||
if (m_engine->breakHandler()->hasPendingBreakpoints()) {
|
||||
if (debugCDBExecution)
|
||||
qDebug("processCreatedAttached: Syncing breakpoints");
|
||||
m_engine->attemptBreakpointSynchronization();
|
||||
}
|
||||
m_engine->attemptBreakpointSynchronization();
|
||||
// Attaching to crashed: This handshake (signalling an event) is required for
|
||||
// the exception to be delivered to the debugger
|
||||
// Also, see special handling in slotModulesLoaded().
|
||||
@@ -1318,7 +1314,7 @@ bool CdbEngine::attemptBreakpointSynchronizationI(QString *errorMessage)
|
||||
switch (handler->state(id)) {
|
||||
case BreakpointInsertRequested:
|
||||
handler->setState(id, BreakpointInsertProceeding);
|
||||
if (addCdbBreakpoint(control, symbols, data, &response, errorMessage)) {
|
||||
if (addCdbBreakpoint(control, symbols, data->parameters(), &response, errorMessage)) {
|
||||
notifyBreakpointInsertOk(id);
|
||||
handler->setResponse(id, response);
|
||||
} else {
|
||||
@@ -1330,7 +1326,7 @@ bool CdbEngine::attemptBreakpointSynchronizationI(QString *errorMessage)
|
||||
// Skip disabled breakpoints, else add
|
||||
handler->setState(id, BreakpointChangeProceeding);
|
||||
if (data->isEnabled()) {
|
||||
if (addCdbBreakpoint(control, symbols, data, &response, errorMessage)) {
|
||||
if (addCdbBreakpoint(control, symbols, data->parameters(), &response, errorMessage)) {
|
||||
notifyBreakpointChangeOk(id);
|
||||
handler->setResponse(id, response);
|
||||
} else {
|
||||
@@ -1348,7 +1344,7 @@ bool CdbEngine::attemptBreakpointSynchronizationI(QString *errorMessage)
|
||||
case BreakpointPending:
|
||||
// Existing breakpoints were deleted due to change/removal, re-set
|
||||
if (syncType == BreakpointsRemovedChanged
|
||||
&& !addCdbBreakpoint(control, symbols, handler->breakpointById(id), &response, errorMessage))
|
||||
&& !addCdbBreakpoint(control, symbols, handler->breakpointById(id)->parameters(), &response, errorMessage))
|
||||
showMessage(*errorMessage, LogError);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -173,6 +173,9 @@ bool searchSymbols(CIDebugSymbols *syms, const QString &pattern,
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *cdbThrowFunction = "CxxThrowException";
|
||||
const char *cdbCatchFunction = "__CxxCallCatchBlock";
|
||||
|
||||
// Helper for the resolveSymbol overloads.
|
||||
static ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol,
|
||||
QStringList *matches,
|
||||
@@ -182,15 +185,9 @@ static ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, QString *symbol,
|
||||
// Is it an incomplete symbol?
|
||||
if (symbol->contains(QLatin1Char('!')))
|
||||
return ResolveSymbolOk;
|
||||
// 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
|
||||
const bool withinMSVCRunTime = *symbol == QLatin1String(cdbThrowFunction)
|
||||
|| *symbol == QLatin1String(cdbCatchFunction);
|
||||
if (*symbol == QLatin1String("qMain")) // 'main' is a #define for gdb, but not for VS
|
||||
*symbol = QLatin1String("main");
|
||||
// resolve
|
||||
if (!searchSymbols(syms, *symbol, matches, errorMessage))
|
||||
|
||||
@@ -64,6 +64,9 @@ ResolveSymbolResult resolveSymbol(CIDebugSymbols *syms, const QString &pattern,
|
||||
bool getModuleSymbols(CIDebugSymbols *syms, const QString &moduleName,
|
||||
QList<Symbol> *symbols, QString *errorMessage);
|
||||
|
||||
extern const char *cdbThrowFunction;
|
||||
extern const char *cdbCatchFunction;
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
@@ -2156,25 +2156,32 @@ static QByteArray addressSpec(quint64 address)
|
||||
QByteArray GdbEngine::breakpointLocation(BreakpointId id)
|
||||
{
|
||||
BreakHandler *handler = breakHandler();
|
||||
QByteArray functionName = handler->functionName(id).toUtf8();
|
||||
if (!functionName.isEmpty()) {
|
||||
// FIXME: Use the types.
|
||||
if (functionName == BreakpointData::throwFunction)
|
||||
return "__cxa_throw";
|
||||
if (functionName == BreakpointData::catchFunction)
|
||||
return "__cxa_begin_catch";
|
||||
const BreakpointData *data = handler->breakpointById(id);
|
||||
QTC_ASSERT(data, return QByteArray());
|
||||
const BreakpointParameters parameters = data->parameters();
|
||||
// FIXME: Non-GCC-runtime
|
||||
if (parameters.type == BreakpointAtThrow)
|
||||
return "__cxa_throw";
|
||||
if (parameters.type == BreakpointAtCatch)
|
||||
return "__cxa_begin_catch";
|
||||
if (parameters.type == BreakpointAtMain)
|
||||
#ifdef Q_OS_WIN
|
||||
return "qMain";
|
||||
#else
|
||||
return "main";
|
||||
#endif
|
||||
const QByteArray functionName = parameters.functionName.toUtf8();
|
||||
if (!functionName.isEmpty())
|
||||
return functionName;
|
||||
}
|
||||
quint64 address = handler->address(id);
|
||||
if (address)
|
||||
if (const quint64 address = handler->address(id))
|
||||
return addressSpec(address);
|
||||
// In this case, data->funcName is something like '*0xdeadbeef'
|
||||
int lineNumber = handler->lineNumber(id);
|
||||
const int lineNumber = handler->lineNumber(id);
|
||||
if (lineNumber == 0)
|
||||
return functionName;
|
||||
QString fileName = handler->fileName(id);
|
||||
if (handler->useFullPath(id))
|
||||
fileName = breakLocation(fileName);
|
||||
const QString fileName = parameters.useFullPath ?
|
||||
breakLocation(parameters.fileName) :
|
||||
parameters.fileName;
|
||||
// The argument is simply a C-quoted version of the argument to the
|
||||
// non-MI "break" command, including the "original" quoting it wants.
|
||||
return "\"\\\"" + GdbMi::escapeCString(fileName).toLocal8Bit() + "\\\":"
|
||||
|
||||
Reference in New Issue
Block a user