forked from qt-creator/qt-creator
debugger: small usability fixes for dissassembler, breakpoint view, location
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include "debuggercore.h"
|
#include "debuggercore.h"
|
||||||
#include "debuggerengine.h"
|
#include "debuggerengine.h"
|
||||||
#include "debuggerstringutils.h"
|
#include "debuggerstringutils.h"
|
||||||
|
#include "stackframe.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needl
|
|||||||
const BreakpointId id = it.key();
|
const BreakpointId id = it.key();
|
||||||
const BreakpointParameters &data = it->data;
|
const BreakpointParameters &data = it->data;
|
||||||
const BreakpointResponse &response = it->response;
|
const BreakpointResponse &response = it->response;
|
||||||
qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
|
//qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
|
||||||
if (response.number && response.number == needle.number)
|
if (response.number && response.number == needle.number)
|
||||||
return id;
|
return id;
|
||||||
|
|
||||||
@@ -353,10 +354,10 @@ BreakpointId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const
|
|||||||
|
|
||||||
BreakpointIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
|
BreakpointIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
|
||||||
{
|
{
|
||||||
BreakpointIds ids;
|
QSet<BreakpointId> ids;
|
||||||
foreach (const QModelIndex &index, list)
|
foreach (const QModelIndex &index, list)
|
||||||
ids.append(findBreakpointByIndex(index));
|
ids.insert(findBreakpointByIndex(index));
|
||||||
return ids;
|
return ids.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
|
Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
|
||||||
@@ -467,7 +468,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
|||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
QString displayValue;
|
QString displayValue;
|
||||||
const quint64 address =
|
const quint64 address =
|
||||||
data.isWatchpoint() ? data.address : response.address;
|
it->isPending() ? data.address : response.address;
|
||||||
if (address)
|
if (address)
|
||||||
displayValue += QString::fromAscii("0x%1").arg(address, 0, 16);
|
displayValue += QString::fromAscii("0x%1").arg(address, 0, 16);
|
||||||
if (!response.extra.isEmpty()) {
|
if (!response.extra.isEmpty()) {
|
||||||
@@ -842,8 +843,17 @@ void BreakHandler::gotoLocation(BreakpointId id) const
|
|||||||
{
|
{
|
||||||
ConstIterator it = m_storage.find(id);
|
ConstIterator it = m_storage.find(id);
|
||||||
QTC_ASSERT(it != m_storage.end(), return);
|
QTC_ASSERT(it != m_storage.end(), return);
|
||||||
debuggerCore()->gotoLocation(
|
if (it->data.type == BreakpointByAddress) {
|
||||||
it->data.fileName, it->data.lineNumber, false);
|
StackFrame frame;
|
||||||
|
frame.address = it->data.address;
|
||||||
|
DebuggerEngine *engine = debuggerCore()->currentEngine();
|
||||||
|
if (engine)
|
||||||
|
engine->gotoLocation(frame, false);
|
||||||
|
} else {
|
||||||
|
const QString fileName = it->markerFileName();
|
||||||
|
const int lineNumber = it->markerLineNumber();
|
||||||
|
debuggerCore()->gotoLocation(fileName, lineNumber, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber)
|
void BreakHandler::updateLineNumberFromMarker(BreakpointId id, int lineNumber)
|
||||||
|
|||||||
@@ -74,13 +74,13 @@ QString BreakpointParameters::toString() const
|
|||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
QTextStream ts(&result);
|
QTextStream ts(&result);
|
||||||
ts << fileName;
|
ts << " FileName: " << fileName;
|
||||||
ts << condition;
|
ts << " Condition: " << condition;
|
||||||
ts << ignoreCount;
|
ts << " IgnoreCount: " << ignoreCount;
|
||||||
ts << lineNumber;
|
ts << " LineNumber: " << lineNumber;
|
||||||
ts << address;
|
ts << " Address: " << address;
|
||||||
ts << functionName;
|
ts << " FunctionName: " << functionName;
|
||||||
ts << useFullPath;
|
ts << " UseFullPath: " << useFullPath;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +99,12 @@ QString BreakpointResponse::toString() const
|
|||||||
{
|
{
|
||||||
QString result;
|
QString result;
|
||||||
QTextStream ts(&result);
|
QTextStream ts(&result);
|
||||||
ts << number;
|
ts << " Number: " << number;
|
||||||
ts << pending;
|
ts << " Pending: " << pending;
|
||||||
ts << fullName;
|
ts << " FullName: " << fullName;
|
||||||
ts << multiple;
|
ts << " Multiple: " << multiple;
|
||||||
ts << extra;
|
ts << " Extra: " << extra;
|
||||||
ts << correctedLineNumber;
|
ts << " CorrectedLineNumber: " << correctedLineNumber;
|
||||||
return result + BreakpointParameters::toString();
|
return result + BreakpointParameters::toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -335,15 +335,6 @@ void BreakWindow::showAddressColumn(bool on)
|
|||||||
setColumnHidden(7, !on);
|
setColumnHidden(7, !on);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QModelIndexList normalizeIndexes(const QModelIndexList &list)
|
|
||||||
{
|
|
||||||
QModelIndexList res;
|
|
||||||
foreach (const QModelIndex &index, list)
|
|
||||||
if (index.column() == 0)
|
|
||||||
res.append(index);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakWindow::keyPressEvent(QKeyEvent *ev)
|
void BreakWindow::keyPressEvent(QKeyEvent *ev)
|
||||||
{
|
{
|
||||||
if (ev->key() == Qt::Key_Delete) {
|
if (ev->key() == Qt::Key_Delete) {
|
||||||
@@ -351,8 +342,11 @@ void BreakWindow::keyPressEvent(QKeyEvent *ev)
|
|||||||
QTC_ASSERT(sm, return);
|
QTC_ASSERT(sm, return);
|
||||||
QModelIndexList si = sm->selectedIndexes();
|
QModelIndexList si = sm->selectedIndexes();
|
||||||
if (si.isEmpty())
|
if (si.isEmpty())
|
||||||
si.append(currentIndex().sibling(currentIndex().row(), 0));
|
si.append(currentIndex());
|
||||||
deleteBreakpoints(normalizeIndexes(si));
|
const BreakpointIds ids = breakHandler()->findBreakpointsByIndex(si);
|
||||||
|
int row = qMin(model()->rowCount() - ids.size() - 1, currentIndex().row());
|
||||||
|
deleteBreakpoints(ids);
|
||||||
|
setCurrentIndex(si.at(0).sibling(row, 0));
|
||||||
}
|
}
|
||||||
QTreeView::keyPressEvent(ev);
|
QTreeView::keyPressEvent(ev);
|
||||||
}
|
}
|
||||||
@@ -365,8 +359,10 @@ void BreakWindow::resizeEvent(QResizeEvent *ev)
|
|||||||
void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev)
|
void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev)
|
||||||
{
|
{
|
||||||
QModelIndex indexUnderMouse = indexAt(ev->pos());
|
QModelIndex indexUnderMouse = indexAt(ev->pos());
|
||||||
if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4)
|
if (indexUnderMouse.isValid() && indexUnderMouse.column() >= 4) {
|
||||||
editBreakpoints(QModelIndexList() << indexUnderMouse);
|
BreakpointId id = breakHandler()->findBreakpointByIndex(indexUnderMouse);
|
||||||
|
editBreakpoints(BreakpointIds() << id);
|
||||||
|
}
|
||||||
QTreeView::mouseDoubleClickEvent(ev);
|
QTreeView::mouseDoubleClickEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,34 +371,35 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
QMenu menu;
|
QMenu menu;
|
||||||
QItemSelectionModel *sm = selectionModel();
|
QItemSelectionModel *sm = selectionModel();
|
||||||
QTC_ASSERT(sm, return);
|
QTC_ASSERT(sm, return);
|
||||||
QModelIndexList si = sm->selectedIndexes();
|
QModelIndexList selectedIndices = sm->selectedIndexes();
|
||||||
QModelIndex indexUnderMouse = indexAt(ev->pos());
|
QModelIndex indexUnderMouse = indexAt(ev->pos());
|
||||||
if (si.isEmpty() && indexUnderMouse.isValid())
|
if (selectedIndices.isEmpty() && indexUnderMouse.isValid())
|
||||||
si.append(indexUnderMouse.sibling(indexUnderMouse.row(), 0));
|
selectedIndices.append(indexUnderMouse);
|
||||||
si = normalizeIndexes(si);
|
|
||||||
|
BreakHandler *handler = breakHandler();
|
||||||
|
BreakpointIds selectedIds = handler->findBreakpointsByIndex(selectedIndices);
|
||||||
|
|
||||||
const int rowCount = model()->rowCount();
|
const int rowCount = model()->rowCount();
|
||||||
const unsigned engineCapabilities = BreakOnThrowAndCatchCapability;
|
const unsigned engineCapabilities = BreakOnThrowAndCatchCapability;
|
||||||
BreakHandler *handler = breakHandler();
|
|
||||||
// FIXME BP: model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
|
// FIXME BP: model()->data(QModelIndex(), EngineCapabilitiesRole).toUInt();
|
||||||
|
|
||||||
QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
|
QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu);
|
||||||
deleteAction->setEnabled(si.size() > 0);
|
deleteAction->setEnabled(!selectedIds.isEmpty());
|
||||||
|
|
||||||
QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu);
|
QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu);
|
||||||
deleteAllAction->setEnabled(model()->rowCount() > 0);
|
deleteAllAction->setEnabled(model()->rowCount() > 0);
|
||||||
|
|
||||||
// Delete by file: Find indices of breakpoints of the same file.
|
// Delete by file: Find indices of breakpoints of the same file.
|
||||||
QAction *deleteByFileAction = 0;
|
QAction *deleteByFileAction = 0;
|
||||||
QList<QModelIndex> breakPointsOfFile;
|
BreakpointIds breakpointsInFile;
|
||||||
if (indexUnderMouse.isValid()) {
|
if (indexUnderMouse.isValid()) {
|
||||||
const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2);
|
const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2);
|
||||||
const QString file = model()->data(index).toString();
|
const QString file = index.data().toString();
|
||||||
if (!file.isEmpty()) {
|
if (!file.isEmpty()) {
|
||||||
for (int i = 0; i < rowCount; i++)
|
for (int i = 0; i < rowCount; i++)
|
||||||
if (model()->data(model()->index(i, 2)).toString() == file)
|
if (index.data().toString() == file)
|
||||||
breakPointsOfFile.push_back(model()->index(i, 2));
|
breakpointsInFile.append(handler->findBreakpointByIndex(index));
|
||||||
if (breakPointsOfFile.size() > 1) {
|
if (breakpointsInFile.size() > 1) {
|
||||||
deleteByFileAction =
|
deleteByFileAction =
|
||||||
new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu);
|
new QAction(tr("Delete Breakpoints of \"%1\"").arg(file), &menu);
|
||||||
deleteByFileAction->setEnabled(true);
|
deleteByFileAction->setEnabled(true);
|
||||||
@@ -425,7 +422,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
|
|
||||||
QAction *editBreakpointAction =
|
QAction *editBreakpointAction =
|
||||||
new QAction(tr("Edit Breakpoint..."), &menu);
|
new QAction(tr("Edit Breakpoint..."), &menu);
|
||||||
editBreakpointAction->setEnabled(si.size() > 0);
|
editBreakpointAction->setEnabled(!selectedIds.isEmpty());
|
||||||
|
|
||||||
int threadId = 0;
|
int threadId = 0;
|
||||||
// FIXME BP: m_engine->threadsHandler()->currentThreadId();
|
// FIXME BP: m_engine->threadsHandler()->currentThreadId();
|
||||||
@@ -433,18 +430,15 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
? tr("Associate Breakpoint With All Threads")
|
? tr("Associate Breakpoint With All Threads")
|
||||||
: tr("Associate Breakpoint With Thread %1").arg(threadId);
|
: tr("Associate Breakpoint With Thread %1").arg(threadId);
|
||||||
QAction *associateBreakpointAction = new QAction(associateTitle, &menu);
|
QAction *associateBreakpointAction = new QAction(associateTitle, &menu);
|
||||||
associateBreakpointAction->setEnabled(si.size() > 0);
|
associateBreakpointAction->setEnabled(!selectedIds.isEmpty());
|
||||||
|
|
||||||
QAction *synchronizeAction =
|
QAction *synchronizeAction =
|
||||||
new QAction(tr("Synchronize Breakpoints"), &menu);
|
new QAction(tr("Synchronize Breakpoints"), &menu);
|
||||||
synchronizeAction->setEnabled(debuggerCore()->hasSnapshots());
|
synchronizeAction->setEnabled(debuggerCore()->hasSnapshots());
|
||||||
|
|
||||||
QModelIndex idx0 = (si.size() ? si.front() : QModelIndex());
|
bool enabled = selectedIds.isEmpty() || handler->isEnabled(selectedIds.at(0));
|
||||||
const BreakpointId id = handler->findBreakpointByIndex(idx0);
|
|
||||||
|
|
||||||
bool enabled = si.isEmpty() || handler->isEnabled(id);
|
const QString str5 = selectedIds.size() > 1
|
||||||
|
|
||||||
const QString str5 = si.size() > 1
|
|
||||||
? enabled
|
? enabled
|
||||||
? tr("Disable Selected Breakpoints")
|
? tr("Disable Selected Breakpoints")
|
||||||
: tr("Enable Selected Breakpoints")
|
: tr("Enable Selected Breakpoints")
|
||||||
@@ -452,7 +446,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
? tr("Disable Breakpoint")
|
? tr("Disable Breakpoint")
|
||||||
: tr("Enable Breakpoint");
|
: tr("Enable Breakpoint");
|
||||||
QAction *toggleEnabledAction = new QAction(str5, &menu);
|
QAction *toggleEnabledAction = new QAction(str5, &menu);
|
||||||
toggleEnabledAction->setEnabled(si.size() > 0);
|
toggleEnabledAction->setEnabled(!selectedIds.isEmpty());
|
||||||
|
|
||||||
QAction *addBreakpointAction =
|
QAction *addBreakpointAction =
|
||||||
new QAction(tr("Add Breakpoint..."), this);
|
new QAction(tr("Add Breakpoint..."), this);
|
||||||
@@ -486,27 +480,24 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
|
|
||||||
QAction *act = menu.exec(ev->globalPos());
|
QAction *act = menu.exec(ev->globalPos());
|
||||||
|
|
||||||
if (act == deleteAction) {
|
if (act == deleteAction)
|
||||||
deleteBreakpoints(si);
|
deleteBreakpoints(selectedIds);
|
||||||
} else if (act == deleteAllAction) {
|
else if (act == deleteAllAction)
|
||||||
QList<QModelIndex> allRows;
|
deleteBreakpoints(handler->allBreakpointIds());
|
||||||
for (int i = 0; i < rowCount; i++)
|
else if (act == deleteByFileAction)
|
||||||
allRows.push_back(model()->index(i, 0));
|
deleteBreakpoints(breakpointsInFile);
|
||||||
deleteBreakpoints(allRows);
|
|
||||||
} else if (act == deleteByFileAction)
|
|
||||||
deleteBreakpoints(breakPointsOfFile);
|
|
||||||
else if (act == adjustColumnAction)
|
else if (act == adjustColumnAction)
|
||||||
resizeColumnsToContents();
|
resizeColumnsToContents();
|
||||||
else if (act == alwaysAdjustAction)
|
else if (act == alwaysAdjustAction)
|
||||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||||
else if (act == editBreakpointAction)
|
else if (act == editBreakpointAction)
|
||||||
editBreakpoints(si);
|
editBreakpoints(selectedIds);
|
||||||
else if (act == associateBreakpointAction)
|
else if (act == associateBreakpointAction)
|
||||||
associateBreakpoint(si, threadId);
|
associateBreakpoint(selectedIds, threadId);
|
||||||
else if (act == synchronizeAction)
|
else if (act == synchronizeAction)
|
||||||
; //synchronizeBreakpoints();
|
; //synchronizeBreakpoints();
|
||||||
else if (act == toggleEnabledAction)
|
else if (act == toggleEnabledAction)
|
||||||
setBreakpointsEnabled(si, !enabled);
|
setBreakpointsEnabled(selectedIds, !enabled);
|
||||||
else if (act == addBreakpointAction)
|
else if (act == addBreakpointAction)
|
||||||
addBreakpoint();
|
addBreakpoint();
|
||||||
else if (act == breakAtThrowAction)
|
else if (act == breakAtThrowAction)
|
||||||
@@ -515,24 +506,17 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
handler->appendBreakpoint(BreakpointParameters(BreakpointAtCatch));
|
handler->appendBreakpoint(BreakpointParameters(BreakpointAtCatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled)
|
void BreakWindow::setBreakpointsEnabled(const BreakpointIds &ids, bool enabled)
|
||||||
{
|
{
|
||||||
BreakHandler *handler = breakHandler();
|
BreakHandler *handler = breakHandler();
|
||||||
foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
|
foreach (const BreakpointId id, ids)
|
||||||
handler->setEnabled(id, enabled);
|
handler->setEnabled(id, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullpath)
|
void BreakWindow::deleteBreakpoints(const BreakpointIds &ids)
|
||||||
{
|
{
|
||||||
BreakHandler *handler = breakHandler();
|
BreakHandler *handler = breakHandler();
|
||||||
foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
|
foreach (const BreakpointId id, ids)
|
||||||
handler->setUseFullPath(id, fullpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BreakWindow::deleteBreakpoints(const QModelIndexList &list)
|
|
||||||
{
|
|
||||||
BreakHandler *handler = breakHandler();
|
|
||||||
foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
|
|
||||||
handler->removeBreakpoint(id);
|
handler->removeBreakpoint(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,15 +536,13 @@ void BreakWindow::addBreakpoint()
|
|||||||
breakHandler()->appendBreakpoint(data);
|
breakHandler()->appendBreakpoint(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakWindow::editBreakpoints(const QModelIndexList &list)
|
void BreakWindow::editBreakpoints(const BreakpointIds &ids)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!list.isEmpty(), return);
|
QTC_ASSERT(!ids.isEmpty(), return);
|
||||||
|
|
||||||
BreakHandler *handler = breakHandler();
|
|
||||||
const BreakpointIds ids = handler->findBreakpointsByIndex(list);
|
|
||||||
const BreakpointId id = ids.at(0);
|
const BreakpointId id = ids.at(0);
|
||||||
|
|
||||||
if (list.size() == 1) {
|
if (ids.size() == 1) {
|
||||||
editBreakpoint(id, this);
|
editBreakpoint(id, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -573,6 +555,7 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
|
|||||||
ui.lineEditIgnoreCount->setValidator(
|
ui.lineEditIgnoreCount->setValidator(
|
||||||
new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
|
new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
|
||||||
|
|
||||||
|
BreakHandler *handler = breakHandler();
|
||||||
const QString oldCondition = QString::fromLatin1(handler->condition(id));
|
const QString oldCondition = QString::fromLatin1(handler->condition(id));
|
||||||
const QString oldIgnoreCount = QString::number(handler->ignoreCount(id));
|
const QString oldIgnoreCount = QString::number(handler->ignoreCount(id));
|
||||||
const QString oldThreadSpec = QString::fromLatin1(handler->threadSpec(id));
|
const QString oldThreadSpec = QString::fromLatin1(handler->threadSpec(id));
|
||||||
@@ -588,23 +571,22 @@ void BreakWindow::editBreakpoints(const QModelIndexList &list)
|
|||||||
const QString newIgnoreCount = ui.lineEditIgnoreCount->text();
|
const QString newIgnoreCount = ui.lineEditIgnoreCount->text();
|
||||||
const QString newThreadSpec = ui.lineEditThreadSpec->text();
|
const QString newThreadSpec = ui.lineEditThreadSpec->text();
|
||||||
|
|
||||||
// Unchanged -> cancel
|
|
||||||
if (newCondition == oldCondition && newIgnoreCount == oldIgnoreCount
|
if (newCondition == oldCondition && newIgnoreCount == oldIgnoreCount
|
||||||
&& newThreadSpec == oldThreadSpec)
|
&& newThreadSpec == oldThreadSpec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (const BreakpointId id, handler->findBreakpointsByIndex(list)) {
|
foreach (const BreakpointId id, ids) {
|
||||||
handler->setCondition(id, newCondition.toLatin1());
|
handler->setCondition(id, newCondition.toLatin1());
|
||||||
handler->setIgnoreCount(id, newIgnoreCount.toInt());
|
handler->setIgnoreCount(id, newIgnoreCount.toInt());
|
||||||
handler->setThreadSpec(id, newThreadSpec.toLatin1());
|
handler->setThreadSpec(id, newThreadSpec.toLatin1());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakWindow::associateBreakpoint(const QModelIndexList &list, int threadId)
|
void BreakWindow::associateBreakpoint(const BreakpointIds &ids, int threadId)
|
||||||
{
|
{
|
||||||
BreakHandler *handler = breakHandler();
|
BreakHandler *handler = breakHandler();
|
||||||
QByteArray spec = QByteArray::number(threadId);
|
QByteArray spec = QByteArray::number(threadId);
|
||||||
foreach (const BreakpointId id, handler->findBreakpointsByIndex(list))
|
foreach (const BreakpointId id, ids)
|
||||||
handler->setThreadSpec(id, spec);
|
handler->setThreadSpec(id, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,12 +61,11 @@ private:
|
|||||||
void keyPressEvent(QKeyEvent *ev);
|
void keyPressEvent(QKeyEvent *ev);
|
||||||
void mouseDoubleClickEvent(QMouseEvent *ev);
|
void mouseDoubleClickEvent(QMouseEvent *ev);
|
||||||
|
|
||||||
void deleteBreakpoints(const QModelIndexList &list);
|
void deleteBreakpoints(const BreakpointIds &ids);
|
||||||
void addBreakpoint();
|
void addBreakpoint();
|
||||||
void editBreakpoints(const QModelIndexList &list);
|
void editBreakpoints(const BreakpointIds &ids);
|
||||||
void associateBreakpoint(const QModelIndexList &list, int thread);
|
void associateBreakpoint(const BreakpointIds &ids, int thread);
|
||||||
void setBreakpointsEnabled(const QModelIndexList &list, bool enabled);
|
void setBreakpointsEnabled(const BreakpointIds &ids, bool enabled);
|
||||||
void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath);
|
|
||||||
|
|
||||||
bool m_alwaysResizeColumnsToContents;
|
bool m_alwaysResizeColumnsToContents;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ struct DisassemblerViewAgentPrivate
|
|||||||
QPointer<TextEditor::ITextEditor> editor;
|
QPointer<TextEditor::ITextEditor> editor;
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
bool tryMixed;
|
bool tryMixed;
|
||||||
|
bool setMarker;
|
||||||
QPointer<DebuggerEngine> engine;
|
QPointer<DebuggerEngine> engine;
|
||||||
LocationMark2 *locationMark;
|
LocationMark2 *locationMark;
|
||||||
QHash<QString, QString> cache;
|
QHash<QString, QString> cache;
|
||||||
@@ -219,6 +220,7 @@ struct DisassemblerViewAgentPrivate
|
|||||||
DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate() :
|
DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate() :
|
||||||
editor(0),
|
editor(0),
|
||||||
tryMixed(true),
|
tryMixed(true),
|
||||||
|
setMarker(true),
|
||||||
locationMark(new LocationMark2),
|
locationMark(new LocationMark2),
|
||||||
mimeType(_("text/x-qtcreator-generic-asm"))
|
mimeType(_("text/x-qtcreator-generic-asm"))
|
||||||
{
|
{
|
||||||
@@ -279,9 +281,11 @@ bool DisassemblerViewAgent::isMixed() const
|
|||||||
&& d->frame.function != _("??");
|
&& d->frame.function != _("??");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed)
|
void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed,
|
||||||
|
bool setMarker)
|
||||||
{
|
{
|
||||||
d->frame = frame;
|
d->frame = frame;
|
||||||
|
d->setMarker = setMarker;
|
||||||
d->tryMixed = tryMixed;
|
d->tryMixed = tryMixed;
|
||||||
if (isMixed()) {
|
if (isMixed()) {
|
||||||
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
|
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
|
||||||
@@ -342,7 +346,7 @@ static QPair<int, int> lineNumberOfAddress(const QString &disassembly, quint64 a
|
|||||||
|
|
||||||
const int size = disassembly.size();
|
const int size = disassembly.size();
|
||||||
for (int lineNumber = 1; pos < size; lineNumber++) {
|
for (int lineNumber = 1; pos < size; lineNumber++) {
|
||||||
int endOfLinePos = disassembly.indexOf(newLine, pos + 1);
|
int endOfLinePos = disassembly.indexOf(newLine, pos);
|
||||||
if (endOfLinePos == -1)
|
if (endOfLinePos == -1)
|
||||||
endOfLinePos = size;
|
endOfLinePos = size;
|
||||||
const QString line = disassembly.mid(pos, endOfLinePos - pos);
|
const QString line = disassembly.mid(pos, endOfLinePos - pos);
|
||||||
@@ -382,11 +386,14 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
|||||||
plainTextEdit->setReadOnly(true);
|
plainTextEdit->setReadOnly(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d->setMarker)
|
||||||
d->editor->markableInterface()->removeMark(d->locationMark);
|
d->editor->markableInterface()->removeMark(d->locationMark);
|
||||||
d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
|
d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
|
||||||
|
|
||||||
const QPair<int, int> lineNumberPos = lineNumberOfAddress(contents, d->frame.address);
|
const QPair<int, int> lineNumberPos =
|
||||||
|
lineNumberOfAddress(contents, d->frame.address);
|
||||||
if (lineNumberPos.first > 0) {
|
if (lineNumberPos.first > 0) {
|
||||||
|
if (d->setMarker)
|
||||||
d->editor->markableInterface()->addMark(d->locationMark, lineNumberPos.first);
|
d->editor->markableInterface()->addMark(d->locationMark, lineNumberPos.first);
|
||||||
if (plainTextEdit) {
|
if (plainTextEdit) {
|
||||||
QTextCursor tc = plainTextEdit->textCursor();
|
QTextCursor tc = plainTextEdit->textCursor();
|
||||||
@@ -399,7 +406,6 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
|||||||
bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
|
bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(d, return false);
|
QTC_ASSERT(d, return false);
|
||||||
|
|
||||||
return lineNumberOfAddress(contents, d->frame.address).first > 0;
|
return lineNumberOfAddress(contents, d->frame.address).first > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public:
|
|||||||
explicit DisassemblerViewAgent(Debugger::DebuggerEngine *engine);
|
explicit DisassemblerViewAgent(Debugger::DebuggerEngine *engine);
|
||||||
~DisassemblerViewAgent();
|
~DisassemblerViewAgent();
|
||||||
|
|
||||||
void setFrame(const StackFrame &frame, bool tryMixed = true);
|
void setFrame(const StackFrame &frame, bool tryMixed, bool setMarker);
|
||||||
const StackFrame &frame() const;
|
const StackFrame &frame() const;
|
||||||
void resetLocation();
|
void resetLocation();
|
||||||
Q_SLOT void setContents(const QString &contents);
|
Q_SLOT void setContents(const QString &contents);
|
||||||
|
|||||||
@@ -516,22 +516,16 @@ void DebuggerEngine::resetLocation()
|
|||||||
|
|
||||||
void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
|
void DebuggerEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
|
||||||
{
|
{
|
||||||
StackFrame frame;
|
debuggerCore()->gotoLocation(fileName, lineNumber, setMarker);
|
||||||
frame.file = fileName;
|
|
||||||
frame.line = lineNumber;
|
|
||||||
gotoLocation(frame, setMarker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
||||||
{
|
{
|
||||||
if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable()) {
|
if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable())
|
||||||
if (setMarker)
|
d->m_disassemblerViewAgent.setFrame(frame, true, setMarker);
|
||||||
resetLocation();
|
else
|
||||||
d->m_disassemblerViewAgent.setFrame(frame);
|
|
||||||
} else {
|
|
||||||
debuggerCore()->gotoLocation(frame.file, frame.line, setMarker);
|
debuggerCore()->gotoLocation(frame.file, frame.line, setMarker);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Called from RunControl.
|
// Called from RunControl.
|
||||||
void DebuggerEngine::handleStartFailed()
|
void DebuggerEngine::handleStartFailed()
|
||||||
|
|||||||
@@ -395,9 +395,27 @@ const char * const SNAPSHOT_KEY = "Ctrl+D,Ctrl+S";
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
} // namespace Debugger
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Cdb {
|
||||||
|
void addCdb2OptionPages(QList<Core::IOptionsPage*> *);
|
||||||
|
} // namespace Cdb
|
||||||
|
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
// FIXME: Outdated?
|
||||||
|
// The createCdbEngine function takes a list of options pages it can add to.
|
||||||
|
// This allows for having a "enabled" toggle on the page independently
|
||||||
|
// of the engine. That's good for not enabling the related ActiveX control
|
||||||
|
// unnecessarily.
|
||||||
|
|
||||||
|
void addGdbOptionPages(QList<IOptionsPage*> *opts);
|
||||||
|
void addScriptOptionPages(QList<IOptionsPage*> *opts);
|
||||||
|
void addTcfOptionPages(QList<IOptionsPage*> *opts);
|
||||||
|
#ifdef CDB_ENABLED
|
||||||
|
void addCdbOptionPages(QList<IOptionsPage*> *opts);
|
||||||
|
#endif
|
||||||
|
|
||||||
static SessionManager *sessionManager()
|
static SessionManager *sessionManager()
|
||||||
{
|
{
|
||||||
@@ -414,41 +432,18 @@ static QToolButton *toolButton(QAction *action)
|
|||||||
// Retrieve file name and line and optionally address
|
// Retrieve file name and line and optionally address
|
||||||
// from the data set on the text editor context menu action.
|
// from the data set on the text editor context menu action.
|
||||||
static bool positionFromContextActionData(const QObject *sender,
|
static bool positionFromContextActionData(const QObject *sender,
|
||||||
QString *fileName,
|
QString *fileName, int *lineNumber, quint64 *address = 0)
|
||||||
int *lineNumber,
|
|
||||||
quint64 *address = 0)
|
|
||||||
{
|
{
|
||||||
if (const QAction *action = qobject_cast<const QAction *>(sender)) {
|
const QAction *action = qobject_cast<const QAction *>(sender);
|
||||||
|
QTC_ASSERT(action, return false);
|
||||||
const QVariantList data = action->data().toList();
|
const QVariantList data = action->data().toList();
|
||||||
if (data.size() >= (address ? 3 : 2)) {
|
QTC_ASSERT(data.size() == 3, return false);
|
||||||
*fileName = data.front().toString();
|
*fileName = data.front().toString();
|
||||||
*lineNumber = data.at(1).toInt();
|
*lineNumber = data.at(1).toInt();
|
||||||
if (address)
|
if (address)
|
||||||
*address = data.at(2).toULongLong();
|
*address = data.at(2).toULongLong();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Debugger {
|
|
||||||
namespace Cdb {
|
|
||||||
void addCdb2OptionPages(QList<Core::IOptionsPage*> *);
|
|
||||||
} // namespace Cdb
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
// FIXME: Outdated?
|
|
||||||
// The createCdbEngine function takes a list of options pages it can add to.
|
|
||||||
// This allows for having a "enabled" toggle on the page independently
|
|
||||||
// of the engine. That's good for not enabling the related ActiveX control
|
|
||||||
// unnecessarily.
|
|
||||||
|
|
||||||
void addGdbOptionPages(QList<IOptionsPage*> *opts);
|
|
||||||
void addScriptOptionPages(QList<IOptionsPage*> *opts);
|
|
||||||
void addTcfOptionPages(QList<IOptionsPage*> *opts);
|
|
||||||
#ifdef CDB_ENABLED
|
|
||||||
void addCdbOptionPages(QList<IOptionsPage*> *opts);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct AttachRemoteParameters
|
struct AttachRemoteParameters
|
||||||
{
|
{
|
||||||
@@ -2391,7 +2386,9 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditor::ITextEditor *editor,
|
|||||||
QString line = editor->contents()
|
QString line = editor->contents()
|
||||||
.section('\n', lineNumber - 1, lineNumber - 1);
|
.section('\n', lineNumber - 1, lineNumber - 1);
|
||||||
BreakpointResponse needle;
|
BreakpointResponse needle;
|
||||||
|
needle.type = BreakpointByAddress;
|
||||||
needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
|
needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
|
||||||
|
address = needle.address;
|
||||||
needle.lineNumber = -1;
|
needle.lineNumber = -1;
|
||||||
id = breakHandler()->findSimilarBreakpoint(needle);
|
id = breakHandler()->findSimilarBreakpoint(needle);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1186,8 +1186,9 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Quickly set the location marker.
|
// Quickly set the location marker.
|
||||||
if (lineNumber && QFileInfo(fullName).exists())
|
if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction)
|
||||||
debuggerCore()->gotoLocation(fullName, lineNumber, true);
|
&& QFileInfo(fullName).exists())
|
||||||
|
gotoLocation(fullName, lineNumber, true);
|
||||||
|
|
||||||
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
|
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
|
||||||
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state())
|
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state())
|
||||||
@@ -1443,7 +1444,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
|||||||
//
|
//
|
||||||
// Stack
|
// Stack
|
||||||
//
|
//
|
||||||
reloadStack(false);
|
reloadStack(false); // Will trigger register reload.
|
||||||
|
|
||||||
if (supportsThreads()) {
|
if (supportsThreads()) {
|
||||||
int currentId = data.findChild("thread-id").data().toInt();
|
int currentId = data.findChild("thread-id").data().toInt();
|
||||||
@@ -1458,11 +1459,6 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
|||||||
CB(handleThreadInfo), currentId);
|
CB(handleThreadInfo), currentId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Registers
|
|
||||||
//
|
|
||||||
reloadRegisters();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleInfoProc(const GdbResponse &response)
|
void GdbEngine::handleInfoProc(const GdbResponse &response)
|
||||||
@@ -2886,8 +2882,7 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &)
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/);
|
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/);
|
||||||
showStatusMessage(tr("Retrieving data for stack view..."), 3000);
|
showStatusMessage(tr("Retrieving data for stack view..."), 3000);
|
||||||
reloadRegisters();
|
reloadStack(true); // Will reload registers.
|
||||||
reloadStack(true);
|
|
||||||
updateLocals();
|
updateLocals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2943,6 +2938,7 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
|
|||||||
// ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
|
// ^error,data={msg="Previous frame identical to this frame (corrupt stack?)"
|
||||||
// logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
|
// logstreamoutput="Previous frame identical to this frame (corrupt stack?)\n"
|
||||||
//qDebug() << "LISTING STACK FAILED: " << response.toString();
|
//qDebug() << "LISTING STACK FAILED: " << response.toString();
|
||||||
|
reloadRegisters();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4039,17 +4035,35 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response)
|
|||||||
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
|
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
|
||||||
GdbMi output = response.data.findChild("consolestreamoutput");
|
GdbMi output = response.data.findChild("consolestreamoutput");
|
||||||
QByteArray res;
|
QByteArray res;
|
||||||
|
QByteArray lastFunction;
|
||||||
foreach (const QByteArray &line0, output.data().split('\n')) {
|
foreach (const QByteArray &line0, output.data().split('\n')) {
|
||||||
QByteArray line = line0.trimmed();
|
QByteArray line = line0.trimmed();
|
||||||
if (line.startsWith("=> "))
|
if (line.startsWith("=> "))
|
||||||
line = line.mid(3);
|
line = line.mid(3);
|
||||||
|
if (line.isEmpty())
|
||||||
|
continue;
|
||||||
if (line.startsWith("Current language:"))
|
if (line.startsWith("Current language:"))
|
||||||
continue;
|
continue;
|
||||||
|
if (line.startsWith("Dump of assembler"))
|
||||||
|
continue;
|
||||||
if (line.startsWith("The current source"))
|
if (line.startsWith("The current source"))
|
||||||
continue;
|
continue;
|
||||||
if (line.startsWith("End of assembler"))
|
if (line.startsWith("End of assembler"))
|
||||||
continue;
|
continue;
|
||||||
if (line.startsWith("0x")) {
|
if (line.startsWith("0x")) {
|
||||||
|
int pos1 = line.indexOf('<') + 1;
|
||||||
|
int pos2 = line.indexOf('+', pos1);
|
||||||
|
int pos3 = line.indexOf('>', pos1);
|
||||||
|
if (pos1 < pos2 && pos2 < pos3) {
|
||||||
|
QByteArray function = line.mid(pos1, pos2 - pos1);
|
||||||
|
if (function != lastFunction) {
|
||||||
|
res.append("\nFunction: ");
|
||||||
|
res.append(function);
|
||||||
|
res.append('\n');
|
||||||
|
lastFunction = function;
|
||||||
|
}
|
||||||
|
line.replace(pos1, pos2 - pos1, "");
|
||||||
|
}
|
||||||
res.append(line);
|
res.append(line);
|
||||||
res.append('\n');
|
res.append('\n');
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
|
|||||||
(void) new MemoryViewAgent(currentEngine(), address);
|
(void) new MemoryViewAgent(currentEngine(), address);
|
||||||
else if (act == actShowDisassembler) {
|
else if (act == actShowDisassembler) {
|
||||||
DisassemblerViewAgent *agent = new DisassemblerViewAgent(engine);
|
DisassemblerViewAgent *agent = new DisassemblerViewAgent(engine);
|
||||||
agent->setFrame(frame);
|
agent->setFrame(frame, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user