Commit 9fc5970b authored by Friedemann Kleint's avatar Friedemann Kleint

Debugger: Introduce BreakpointParameters as base struct.

For Breakpoint data manipulation.

Reviewed-by: hjk
parent 50dc4d86
......@@ -97,26 +97,26 @@ static bool isSimilarTo(const BreakpointData &data, const BreakpointResponse &ne
{
// Clear hit.
// Clear miss.
if (needle.bpType != UnknownType && data.type() != UnknownType
&& data.type() != needle.bpType)
if (needle.type != UnknownType && data.type() != UnknownType
&& data.type() != needle.type)
return false;
// Clear hit.
if (data.address() && data.address() == needle.bpAddress)
if (data.address() && data.address() == needle.address)
return true;
// At least at a position we were looking for.
// FIXME: breaks multiple breakpoints at the same location
if (!data.fileName().isEmpty()
&& fileNameMatch(data.fileName(), needle.bpFileName)
&& data.lineNumber() == needle.bpLineNumber)
&& fileNameMatch(data.fileName(), needle.fileName)
&& data.lineNumber() == needle.lineNumber)
return true;
// At least at a position we were looking for.
// FIXME: breaks multiple breakpoints at the same location
if (!data.fileName().isEmpty()
&& fileNameMatch(data.fileName(), needle.bpFileName)
&& data.lineNumber() == needle.bpLineNumber)
&& fileNameMatch(data.fileName(), needle.fileName)
&& data.lineNumber() == needle.lineNumber)
return true;
return false;
......@@ -131,7 +131,7 @@ BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needl
const BreakpointData &data = it->data;
const BreakpointResponse &response = it->response;
qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
if (response.bpNumber && response.bpNumber == needle.bpNumber)
if (response.number && response.number == needle.number)
return id;
if (isSimilarTo(data, needle))
......@@ -144,7 +144,7 @@ BreakpointId BreakHandler::findBreakpointByNumber(int bpNumber) const
{
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
for ( ; it != et; ++it)
if (it->response.bpNumber == bpNumber)
if (it->response.number == bpNumber)
return it.key();
return BreakpointId(-1);
}
......@@ -377,7 +377,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
case 0:
if (role == Qt::DisplayRole) {
return QString::number(id);
//return QString("%1 - %2").arg(id).arg(response.bpNumber);
//return QString("%1 - %2").arg(id).arg(response.number);
}
if (role == Qt::DecorationRole) {
if (data.isWatchpoint())
......@@ -390,14 +390,14 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
case 1:
if (role == Qt::DisplayRole) {
const QString str = it->isPending()
? data.functionName() : response.bpFuncName;
? data.functionName() : response.functionName;
return str.isEmpty() ? empty : str;
}
break;
case 2:
if (role == Qt::DisplayRole) {
QString str = it->isPending()
? data.fileName() : response.bpFileName;
? data.fileName() : response.fileName;
str = QFileInfo(str).fileName();
// FIXME: better?
//if (data.bpMultiple && str.isEmpty() && !data.markerFileName.isEmpty())
......@@ -414,7 +414,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
//if (data.bpMultiple && str.isEmpty() && !data.markerFileName.isEmpty())
// str = data.markerLineNumber;
const int nr = it->isPending()
? data.lineNumber() : response.bpLineNumber;
? data.lineNumber() : response.lineNumber;
return nr ? QString::number(nr) : empty;
}
if (role == Qt::UserRole + 1)
......@@ -422,7 +422,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
break;
case 4:
if (role == Qt::DisplayRole)
return it->isPending() ? data.condition() : response.bpCondition;
return it->isPending() ? data.condition() : response.condition;
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit if this condition is met.");
if (role == Qt::UserRole + 1)
......@@ -431,7 +431,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
case 5:
if (role == Qt::DisplayRole) {
const int ignoreCount =
it->isPending() ? data.ignoreCount() : response.bpIgnoreCount;
it->isPending() ? data.ignoreCount() : response.ignoreCount;
return ignoreCount ? QVariant(ignoreCount) : QVariant(QString());
}
if (role == Qt::ToolTipRole)
......@@ -444,7 +444,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
if (it->isPending())
return !data.threadSpec().isEmpty() ? data.threadSpec() : tr("(all)");
else
return !response.bpThreadSpec.isEmpty() ? response.bpThreadSpec : tr("(all)");
return !response.threadSpec.isEmpty() ? response.threadSpec : tr("(all)");
}
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit in the specified thread(s).");
......@@ -455,13 +455,13 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
if (role == Qt::DisplayRole) {
QString displayValue;
const quint64 address =
data.isWatchpoint() ? data.address() : response.bpAddress;
data.isWatchpoint() ? data.address() : response.address;
if (address)
displayValue += QString::fromAscii("0x%1").arg(address, 0, 16);
if (!response.bpState.isEmpty()) {
if (!response.state.isEmpty()) {
if (!displayValue.isEmpty())
displayValue += QLatin1Char(' ');
displayValue += QString::fromAscii(response.bpState);
displayValue += QString::fromAscii(response.state);
}
return displayValue;
}
......@@ -516,7 +516,7 @@ PROPERTY(int, ignoreCount, setIgnoreCount)
bool BreakHandler::isEnabled(BreakpointId id) const
{
ConstIterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return BreakpointDead);
QTC_ASSERT(it != m_storage.end(), return false);
return it->data.isEnabled();
}
......@@ -576,7 +576,7 @@ void BreakHandler::ackCondition(BreakpointId id)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response.bpCondition = it->data.condition();
it->response.condition = it->data.condition();
updateMarker(id);
}
......@@ -584,7 +584,7 @@ void BreakHandler::ackIgnoreCount(BreakpointId id)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response.bpIgnoreCount = it->data.ignoreCount();
it->response.ignoreCount = it->data.ignoreCount();
updateMarker(id);
}
......@@ -592,7 +592,7 @@ void BreakHandler::ackEnabled(BreakpointId id)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
it->response.bpEnabled = it->data.isEnabled();
it->response.enabled = it->data.isEnabled();
updateMarker(id);
}
......@@ -751,7 +751,7 @@ void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber)
// running, as this can be triggered by moving the breakpoint to
// the next line that generated code.
// FIXME: Do we need yet another data member?
if (it->response.bpNumber == 0) {
if (it->response.number == 0) {
it->data.setLineNumber(lineNumber);
updateMarker(id);
}
......@@ -925,36 +925,36 @@ QString BreakHandler::BreakpointItem::toToolTip() const
<< "<tr><td>" << tr("Marker Line:")
<< "</td><td>" << data.m_markerLineNumber << "</td></tr>"
<< "<tr><td>" << tr("Breakpoint Number:")
<< "</td><td>" << response.bpNumber << "</td></tr>"
<< "</td><td>" << response.number << "</td></tr>"
<< "<tr><td>" << tr("Breakpoint Type:")
<< "</td><td>" << t << "</td></tr>"
<< "<tr><td>" << tr("State:")
<< "</td><td>" << response.bpState << "</td></tr>"
<< "</td><td>" << response.state << "</td></tr>"
<< "</table><br><hr><table>"
<< "<tr><th>" << tr("Property")
<< "</th><th>" << tr("Requested")
<< "</th><th>" << tr("Obtained") << "</th></tr>"
<< "<tr><td>" << tr("Internal Number:")
<< "</td><td>&mdash;</td><td>" << response.bpNumber << "</td></tr>"
<< "</td><td>&mdash;</td><td>" << response.number << "</td></tr>"
<< "<tr><td>" << tr("File Name:")
<< "</td><td>" << QDir::toNativeSeparators(data.m_fileName)
<< "</td><td>" << QDir::toNativeSeparators(response.bpFileName)
<< "</td><td>" << QDir::toNativeSeparators(data.fileName())
<< "</td><td>" << QDir::toNativeSeparators(response.fileName)
<< "</td></tr>"
<< "<tr><td>" << tr("Function Name:")
<< "</td><td>" << data.m_functionName
<< "</td><td>" << response.bpFuncName << "</td></tr>"
<< "</td><td>" << data.functionName()
<< "</td><td>" << response.functionName << "</td></tr>"
<< "<tr><td>" << tr("Line Number:") << "</td><td>";
if (data.m_lineNumber)
str << data.m_lineNumber;
if (data.lineNumber())
str << data.lineNumber();
str << "</td><td>";
if (response.bpLineNumber)
str << response.bpLineNumber;
if (response.lineNumber)
str << response.lineNumber;
str << "</td></tr>"
<< "<tr><td>" << tr("Breakpoint Address:")
<< "</td><td>";
formatAddress(str, data.m_address);
formatAddress(str, data.address());
str << "</td><td>";
formatAddress(str, response.bpAddress);
formatAddress(str, response.address);
//str << "</td></tr>"
// << "<tr><td>" << tr("Corrected Line Number:")
// << "</td><td>-</td><td>";
......@@ -964,18 +964,18 @@ QString BreakHandler::BreakpointItem::toToolTip() const
// str << '-';
str << "</td></tr>"
<< "<tr><td>" << tr("Condition:")
<< "</td><td>" << data.m_condition
<< "</td><td>" << response.bpCondition << "</td></tr>"
<< "</td><td>" << data.condition()
<< "</td><td>" << response.condition << "</td></tr>"
<< "<tr><td>" << tr("Ignore Count:") << "</td><td>";
if (data.m_ignoreCount)
str << data.m_ignoreCount;
if (data.ignoreCount())
str << data.ignoreCount();
str << "</td><td>";
if (response.bpIgnoreCount)
str << response.bpIgnoreCount;
if (response.ignoreCount)
str << response.ignoreCount;
str << "</td></tr>"
<< "<tr><td>" << tr("Thread Specification:")
<< "</td><td>" << data.m_threadSpec
<< "</td><td>" << response.bpThreadSpec << "</td></tr>"
<< "</td><td>" << data.threadSpec()
<< "</td><td>" << response.threadSpec << "</td></tr>"
<< "</table></body></html>";
return rc;
}
......
......@@ -44,32 +44,36 @@ namespace Internal {
const char *BreakpointData::throwFunction = "throw";
const char *BreakpointData::catchFunction = "catch";
BreakpointData::BreakpointData(BreakpointType type)
BreakpointParameters::BreakpointParameters(BreakpointType t) :
type(t), enabled(type), useFullPath(false),
ignoreCount(0), lineNumber(0)
{
m_type = type;
m_enabled = true;
m_ignoreCount = 0;
m_lineNumber = 0;
m_address = 0;
m_useFullPath = false;
m_markerLineNumber = 0;
}
BreakpointResponse::BreakpointResponse()
bool BreakpointParameters::equals(const BreakpointParameters &rhs) const
{
return type != rhs.type && enabled == rhs.enabled
&& useFullPath == rhs.useFullPath
&& fileName == rhs.fileName && condition == rhs.condition
&& ignoreCount == rhs.ignoreCount && lineNumber == rhs.lineNumber
&& address == rhs.address && threadSpec == rhs.threadSpec
&& functionName == rhs.functionName;
}
BreakpointData::BreakpointData(BreakpointType type) :
m_parameters(type), m_markerLineNumber(0)
{
}
BreakpointResponse::BreakpointResponse() :
number(0), multiple(false)
{
bpNumber = 0;
bpIgnoreCount = 0;
bpLineNumber = 0;
//bpCorrectedLineNumber = 0;
bpAddress = 0;
bpMultiple = false;
bpEnabled = true;
}
#define SETIT(var, value) return (var != value) && (var = value, true)
bool BreakpointData::setUseFullPath(bool on)
{ SETIT(m_useFullPath, on); }
{ SETIT(m_parameters.useFullPath, on); }
bool BreakpointData::setMarkerFileName(const QString &file)
{ SETIT(m_markerFileName, file); }
......@@ -78,31 +82,31 @@ bool BreakpointData::setMarkerLineNumber(int line)
{ SETIT(m_markerLineNumber, line); }
bool BreakpointData::setFileName(const QString &file)
{ SETIT(m_fileName, file); }
{ SETIT(m_parameters.fileName, file); }
bool BreakpointData::setEnabled(bool on)
{ SETIT(m_enabled, on); }
{ SETIT(m_parameters.enabled, on); }
bool BreakpointData::setIgnoreCount(int count)
{ SETIT(m_ignoreCount, count); }
{ SETIT(m_parameters.ignoreCount, count); }
bool BreakpointData::setFunctionName(const QString &name)
{ SETIT(m_functionName, name); }
{ SETIT(m_parameters.functionName, name); }
bool BreakpointData::setLineNumber(int line)
{ SETIT(m_lineNumber, line); }
{ SETIT(m_parameters.lineNumber, line); }
bool BreakpointData::setAddress(quint64 address)
{ SETIT(m_address, address); }
{ SETIT(m_parameters.address, address); }
bool BreakpointData::setThreadSpec(const QByteArray &spec)
{ SETIT(m_threadSpec, spec); }
{ SETIT(m_parameters.threadSpec, spec); }
bool BreakpointData::setType(BreakpointType type)
{ SETIT(m_type, type); }
{ SETIT(m_parameters.type, type); }
bool BreakpointData::setCondition(const QByteArray &cond)
{ SETIT(m_condition, cond); }
{ SETIT(m_parameters.condition, cond); }
#undef SETIT
......@@ -120,14 +124,14 @@ static inline bool fileNameMatch(const QString &f1, const QString &f2)
bool BreakpointData::isLocatedAt(const QString &fileName, int lineNumber,
bool useMarkerPosition) const
{
int line = useMarkerPosition ? m_markerLineNumber : m_lineNumber;
int line = useMarkerPosition ? m_markerLineNumber : m_parameters.lineNumber;
return lineNumber == line && fileNameMatch(fileName, m_markerFileName);
}
bool BreakpointData::conditionsMatch(const QByteArray &other) const
{
// Some versions of gdb "beautify" the passed condition.
QByteArray s1 = m_condition;
QByteArray s1 = m_parameters.condition;
s1.replace(' ', "");
QByteArray s2 = other;
s2.replace(' ', "");
......@@ -152,15 +156,15 @@ QString BreakpointResponse::toString() const
{
QString result;
QTextStream ts(&result);
ts << bpNumber;
ts << bpCondition;
ts << bpIgnoreCount;
ts << bpFileName;
ts << bpFullName;
ts << bpLineNumber;
ts << bpThreadSpec;
ts << bpFuncName;
ts << bpAddress;
ts << number;
ts << condition;
ts << ignoreCount;
ts << fileName;
ts << fullName;
ts << lineNumber;
ts << threadSpec;
ts << functionName;
ts << address;
return result;
}
......
......@@ -81,6 +81,28 @@ enum BreakpointState
BreakpointDead,
};
class BreakpointParameters {
public:
explicit BreakpointParameters(BreakpointType = UnknownType);
bool equals(const BreakpointParameters &rhs) const;
BreakpointType type; // Type of breakpoint.
bool enabled; // Should we talk to the debugger engine?
bool useFullPath; // Should we use the full path when setting the bp?
QString fileName; // Short name of source file.
QByteArray condition; // Condition associated with breakpoint.
int ignoreCount; // Ignore count associated with breakpoint.
int lineNumber; // Line in source file.
quint64 address; // Address for watchpoints.
QByteArray threadSpec; // Thread specification.
QString functionName;
};
inline bool operator==(const BreakpointParameters &p1, const BreakpointParameters &p2)
{ return p1.equals(p2); }
inline bool operator!=(const BreakpointParameters &p1, const BreakpointParameters &p2)
{ return !p1.equals(p2); }
class BreakpointData
{
private:
......@@ -92,26 +114,27 @@ private:
public:
explicit BreakpointData(BreakpointType = UnknownType);
BreakpointType type() const { return m_type; }
quint64 address() const { return m_address; }
bool useFullPath() const { return m_useFullPath; }
BreakpointType type() const { return m_parameters.type; }
quint64 address() const { return m_parameters.address; }
bool useFullPath() const { return m_parameters.useFullPath; }
QString toString() const;
bool isLocatedAt(const QString &fileName, int lineNumber,
bool useMarkerPosition) const;
bool conditionsMatch(const QByteArray &other) const;
QString functionName() const { return m_functionName; }
QString functionName() const { return m_parameters.functionName; }
QString markerFileName() const { return m_markerFileName; }
QString fileName() const { return m_fileName; }
QString fileName() const { return m_parameters.fileName; }
int markerLineNumber() const { return m_markerLineNumber; }
int lineNumber() const { return m_lineNumber; }
int ignoreCount() const { return m_ignoreCount; }
bool isEnabled() const { return m_enabled; }
QByteArray threadSpec() const { return m_threadSpec; }
QByteArray condition() const { return m_condition; }
bool isWatchpoint() const { return m_type == Watchpoint; }
bool isBreakpoint() const { return m_type != Watchpoint; } // Enough for now.
int lineNumber() const { return m_parameters.lineNumber; }
int ignoreCount() const { return m_parameters.ignoreCount; }
bool isEnabled() const { return m_parameters.enabled; }
QByteArray threadSpec() const { return m_parameters.threadSpec; }
QByteArray condition() const { return m_parameters.condition; }
const BreakpointParameters &parameters() const { return m_parameters; }
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;
......@@ -133,18 +156,7 @@ private:
private:
// This "user requested information" will get stored in the session.
BreakpointType m_type; // Type of breakpoint.
bool m_enabled; // Should we talk to the debugger engine?
bool m_useFullPath; // Should we use the full path when setting the bp?
QString m_fileName; // Short name of source file.
QByteArray m_condition; // Condition associated with breakpoint.
int m_ignoreCount; // Ignore count associated with breakpoint.
int m_lineNumber; // Line in source file.
quint64 m_address; // Address for watchpoints.
QByteArray m_threadSpec; // Thread specification.
// Name of containing function, special values:
// BreakpointData::throwFunction, BreakpointData::catchFunction
QString m_functionName;
BreakpointParameters m_parameters;
QString m_markerFileName; // Used to locate the marker.
int m_markerLineNumber;
......@@ -154,27 +166,17 @@ public:
// This is what debuggers produced in response to the attempt to
// insert a breakpoint. The data might differ from the requested bits.
class BreakpointResponse
class BreakpointResponse : public BreakpointParameters
{
public:
BreakpointResponse();
QString toString() const;
public:
int bpNumber; // Breakpoint number assigned by the debugger engine.
BreakpointType bpType; // Breakpoint type used by debugger engine.
QByteArray bpCondition; // Condition acknowledged by the debugger engine.
int bpIgnoreCount; // Ignore count acknowledged by the debugger engine.
QString bpFileName; // File name acknowledged by the debugger engine.
QString bpFullName; // Full file name acknowledged by the debugger engine.
int bpLineNumber; // Line number acknowledged by the debugger engine.
//int bpCorrectedLineNumber; // Acknowledged by the debugger engine.
QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine.
QString bpFuncName; // Function name acknowledged by the debugger engine.
quint64 bpAddress; // Address acknowledged by the debugger engine.
bool bpMultiple; // Happens in constructors/gdb.
bool bpEnabled; // Enable/disable command sent.
QByteArray bpState; // gdb: <PENDING>, <MULTIPLE>
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.
QByteArray state; // gdb: <PENDING>, <MULTIPLE>
};
typedef QList<BreakpointId> BreakpointIds;
......
......@@ -71,16 +71,16 @@ static inline QString msgCannotSetBreakAtFunction(const QString &func, const QSt
void setBreakpointResponse(const BreakpointData *nbd, int number, BreakpointResponse *response)
{
response->bpAddress = nbd->address();
response->bpNumber = number;
response->bpFuncName = nbd->functionName();
response->bpType = nbd->type();
response->bpCondition = nbd->condition();
response->bpIgnoreCount = nbd->ignoreCount();
response->bpFullName = response->bpFileName = nbd->fileName();
response->bpLineNumber = nbd->lineNumber();
response->bpThreadSpec = nbd->threadSpec();
response->bpEnabled = nbd->isEnabled();
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();
}
bool addCdbBreakpoint(CIDebugControl* debugControl,
......@@ -116,8 +116,8 @@ bool addCdbBreakpoint(CIDebugControl* debugControl,
if (debugBreakpoints)
qDebug("Added %lu at 0x%lx %s", id, address, qPrintable(ncdbbp.toString()));
setBreakpointResponse(nbd, id, response);
response->bpAddress = address;
response->bpFuncName = resolvedFunction;
response->address = address;
response->functionName = resolvedFunction;
return true;
}
......
......@@ -2293,8 +2293,8 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor,
QString line = editor->contents()
.section('\n', lineNumber - 1, lineNumber - 1);
BreakpointResponse needle;
needle.bpAddress = DisassemblerViewAgent::addressFromDisassemblyLine(line);
needle.bpLineNumber = -1;
needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
needle.lineNumber = -1;
id = breakHandler()->findSimilarBreakpoint(needle);
} else {
fileName = editor->file()->fileName();
......
......@@ -136,31 +136,31 @@ QDataStream &operator>>(QDataStream &stream, StackFrames &frames)
QDataStream &operator<<(QDataStream &stream, const BreakpointResponse &s)
{
stream << s.bpNumber;
stream << s.bpCondition;
stream << s.bpIgnoreCount;
stream << s.bpFileName;
stream << s.bpFullName;
stream << s.bpLineNumber;
stream << s.number;
stream << s.condition;
stream << s.ignoreCount;
stream << s.fileName;
stream << s.fullName;
stream << s.lineNumber;
//stream << s.bpCorrectedLineNumber;
stream << s.bpThreadSpec;
stream << s.bpFuncName;
stream << s.bpAddress;
stream << s.threadSpec;
stream << s.functionName;
stream << s.address;
return stream;
}
QDataStream &operator>>(QDataStream &stream, BreakpointResponse &s)
{
stream >> s.bpNumber;
stream >> s.bpCondition;
stream >> s.bpIgnoreCount;
stream >> s.bpFileName;
stream >> s.bpFullName;
stream >> s.bpLineNumber;
stream >> s.number;
stream >> s.condition;
stream >> s.ignoreCount;
stream >> s.fileName;