forked from qt-creator/qt-creator
Debugger: Polish register view
Right-align subregister values, drop the 0x prefix for hex values, add a subitem with ASCII representation and tooltips for subitems. Change-Id: I6a5764fa5ef8b2bfd916cdd828d949a82304503d Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
@@ -252,14 +252,29 @@ void Register::guessMissingData()
|
||||
fixup(this, IntegerRegister, 0);
|
||||
}
|
||||
|
||||
static QString subTypeName(RegisterKind kind, int size)
|
||||
static QString subTypeName(RegisterKind kind, int size, RegisterFormat format)
|
||||
{
|
||||
if (kind == IntegerRegister)
|
||||
return QString::fromLatin1("[i%1]").arg(size * 8);
|
||||
if (kind == FloatRegister)
|
||||
return QString::fromLatin1("[f%1]").arg(size * 8);
|
||||
QTC_ASSERT(false, /**/);
|
||||
return QString();
|
||||
QString name(QLatin1Char('['));
|
||||
|
||||
switch (kind) {
|
||||
case IntegerRegister: name += QLatin1Char('i'); break;
|
||||
case FloatRegister: name += QLatin1Char('f'); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
name += QString::number(size);
|
||||
|
||||
switch (format) {
|
||||
case BinaryFormat: name += QLatin1Char('b'); break;
|
||||
case OctalFormat: name += QLatin1Char('o'); break;
|
||||
case DecimalFormat: name += QLatin1Char('d'); break;
|
||||
case HexadecimalFormat: name += QLatin1Char('x'); break;
|
||||
case CharacterFormat: name += QLatin1Char('c'); break;
|
||||
}
|
||||
|
||||
name += QLatin1Char(']');
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static uint decodeHexChar(unsigned char c)
|
||||
@@ -305,15 +320,29 @@ bool RegisterValue::operator==(const RegisterValue &other)
|
||||
return v.u64[0] == other.v.u64[0] && v.u64[1] == other.v.u64[1];
|
||||
}
|
||||
|
||||
static QByteArray format(quint64 v, int base, int size)
|
||||
static QByteArray formatRegister(quint64 v, int size, RegisterFormat format)
|
||||
{
|
||||
QByteArray result = QByteArray::number(v, base);
|
||||
if (base == 16)
|
||||
QByteArray result;
|
||||
if (format == HexadecimalFormat) {
|
||||
result = QByteArray::number(v, 16);
|
||||
result.prepend(QByteArray(2*size - result.size(), '0'));
|
||||
} else if (format == DecimalFormat) {
|
||||
result = QByteArray::number(v, 10);
|
||||
result.prepend(QByteArray(2*size - result.size(), ' '));
|
||||
} else if (format == CharacterFormat) {
|
||||
if (v >= 32 && v < 127) {
|
||||
result += '\'';
|
||||
result += char(v);
|
||||
result += '\'';
|
||||
} else {
|
||||
result += " ";
|
||||
}
|
||||
result.prepend(QByteArray(2*size - result.size(), ' '));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray RegisterValue::toByteArray(int base, RegisterKind kind, int size) const
|
||||
QByteArray RegisterValue::toByteArray(RegisterKind kind, int size, RegisterFormat format) const
|
||||
{
|
||||
if (!known)
|
||||
return "[inaccessible]";
|
||||
@@ -326,15 +355,12 @@ QByteArray RegisterValue::toByteArray(int base, RegisterKind kind, int size) con
|
||||
|
||||
QByteArray result;
|
||||
if (size > 8) {
|
||||
result += format(v.u64[1], base, size - 8);
|
||||
result += formatRegister(v.u64[1], size - 8, format);
|
||||
size = 8;
|
||||
if (base != 16)
|
||||
if (format != HexadecimalFormat)
|
||||
result += ',';
|
||||
}
|
||||
result += format(v.u64[0], base, size);
|
||||
if (base == 16)
|
||||
result.prepend("0x");
|
||||
return result;
|
||||
return result + formatRegister(v.u64[0], size, format);
|
||||
}
|
||||
|
||||
RegisterValue RegisterValue::subValue(int size, int index) const
|
||||
@@ -367,8 +393,8 @@ RegisterValue RegisterValue::subValue(int size, int index) const
|
||||
class RegisterSubItem : public Utils::TreeItem
|
||||
{
|
||||
public:
|
||||
RegisterSubItem(RegisterKind subKind, int subSize, int count)
|
||||
: m_subKind(subKind), m_subSize(subSize), m_count(count), m_changed(false)
|
||||
RegisterSubItem(RegisterKind subKind, int subSize, int count, RegisterFormat format)
|
||||
: m_subKind(subKind), m_subFormat(format), m_subSize(subSize), m_count(count), m_changed(false)
|
||||
{}
|
||||
|
||||
QVariant data(int column, int role) const;
|
||||
@@ -382,6 +408,7 @@ public:
|
||||
}
|
||||
|
||||
RegisterKind m_subKind;
|
||||
RegisterFormat m_subFormat;
|
||||
int m_subSize;
|
||||
int m_count;
|
||||
bool m_changed;
|
||||
@@ -398,23 +425,27 @@ public:
|
||||
quint64 addressValue() const;
|
||||
|
||||
Register m_reg;
|
||||
int m_base;
|
||||
RegisterFormat m_format;
|
||||
bool m_changed;
|
||||
};
|
||||
|
||||
RegisterItem::RegisterItem(const Register ®) :
|
||||
m_reg(reg), m_base(16), m_changed(true)
|
||||
m_reg(reg), m_format(HexadecimalFormat), m_changed(true)
|
||||
{
|
||||
if (m_reg.kind == UnknownRegister)
|
||||
m_reg.guessMissingData();
|
||||
|
||||
if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) {
|
||||
for (int s = m_reg.size / 2; s; s = s / 2)
|
||||
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s));
|
||||
for (int s = m_reg.size / 2; s; s = s / 2) {
|
||||
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, HexadecimalFormat));
|
||||
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, DecimalFormat));
|
||||
if (s == 1)
|
||||
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, CharacterFormat));
|
||||
}
|
||||
}
|
||||
if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) {
|
||||
for (int s = m_reg.size; s >= 4; s = s / 2)
|
||||
appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s));
|
||||
appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s, DecimalFormat));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,12 +475,12 @@ QVariant RegisterItem::data(int column, int role) const
|
||||
case RegisterChangedRole:
|
||||
return m_changed;
|
||||
|
||||
case RegisterNumberBaseRole:
|
||||
return m_base;
|
||||
|
||||
case RegisterAsAddressRole:
|
||||
return addressValue();
|
||||
|
||||
case RegisterFormatRole:
|
||||
return m_format;
|
||||
|
||||
case Qt::DisplayRole:
|
||||
switch (column) {
|
||||
case RegisterNameColumn: {
|
||||
@@ -459,17 +490,17 @@ QVariant RegisterItem::data(int column, int role) const
|
||||
return res;
|
||||
}
|
||||
case RegisterValueColumn: {
|
||||
return m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size);
|
||||
return m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format);
|
||||
}
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
return QString::fromLatin1("Current Value: %1\nPreviousValue: %2")
|
||||
.arg(QString::fromLatin1(m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size)))
|
||||
.arg(QString::fromLatin1(m_reg.previousValue.toByteArray(m_base, m_reg.kind, m_reg.size)));
|
||||
.arg(QString::fromLatin1(m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format)))
|
||||
.arg(QString::fromLatin1(m_reg.previousValue.toByteArray(m_reg.kind, m_reg.size, m_format)));
|
||||
|
||||
case Qt::EditRole: // Edit: Unpadded for editing
|
||||
return m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size);
|
||||
return m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format);
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
return column == RegisterValueColumn ? QVariant(Qt::AlignRight) : QVariant();
|
||||
@@ -486,8 +517,10 @@ QVariant RegisterSubItem::data(int column, int role) const
|
||||
case RegisterChangedRole:
|
||||
return m_changed;
|
||||
|
||||
case RegisterNumberBaseRole:
|
||||
return 16;
|
||||
case RegisterFormatRole: {
|
||||
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
|
||||
return int(registerItem->m_format);
|
||||
}
|
||||
|
||||
case RegisterAsAddressRole:
|
||||
return 0;
|
||||
@@ -495,20 +528,32 @@ QVariant RegisterSubItem::data(int column, int role) const
|
||||
case Qt::DisplayRole:
|
||||
switch (column) {
|
||||
case RegisterNameColumn:
|
||||
return subTypeName(m_subKind, m_subSize);
|
||||
return subTypeName(m_subKind, m_subSize, m_subFormat);
|
||||
case RegisterValueColumn: {
|
||||
QTC_ASSERT(parent(), return QVariant());
|
||||
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
|
||||
RegisterValue value = registerItem->m_reg.value;
|
||||
QByteArray ba;
|
||||
for (int i = 0; i != m_count; ++i) {
|
||||
ba += value.subValue(m_subSize, i).toByteArray(16, m_subKind, m_subSize);
|
||||
int tab = 5 * (i + 1) * m_subSize;
|
||||
ba += QByteArray(tab - ba.size(), ' ');
|
||||
QByteArray b = value.subValue(m_subSize, i).toByteArray(m_subKind, m_subSize, m_subFormat);
|
||||
ba += QByteArray(tab - ba.size() - b.size(), ' ');
|
||||
ba += b;
|
||||
}
|
||||
return ba;
|
||||
}
|
||||
}
|
||||
|
||||
case Qt::ToolTipRole:
|
||||
if (m_subKind == IntegerRegister) {
|
||||
if (m_subFormat == CharacterFormat)
|
||||
return RegisterHandler::tr("Content as ASCII Characters");
|
||||
else
|
||||
return RegisterHandler::tr("Content as %1-bit Integer Values").arg(8 * m_subSize);
|
||||
}
|
||||
if (m_subKind == FloatRegister)
|
||||
return RegisterHandler::tr("Contents as %1-bit Floating Point Values").arg(8 * m_subSize);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -553,11 +598,11 @@ void RegisterHandler::updateRegister(const Register &r)
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHandler::setNumberBase(const QByteArray &name, int base)
|
||||
void RegisterHandler::setNumberFormat(const QByteArray &name, RegisterFormat format)
|
||||
{
|
||||
RegisterItem *reg = m_registerByName.value(name, 0);
|
||||
QTC_ASSERT(reg, return);
|
||||
reg->m_base = base;
|
||||
reg->m_format = format;
|
||||
QModelIndex index = indexFromItem(reg);
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ enum RegisterDataRole
|
||||
RegisterNameRole = Qt::UserRole,
|
||||
RegisterIsBigRole,
|
||||
RegisterChangedRole,
|
||||
RegisterNumberBaseRole,
|
||||
RegisterFormatRole,
|
||||
RegisterAsAddressRole
|
||||
};
|
||||
|
||||
@@ -66,6 +66,15 @@ enum RegisterKind
|
||||
OtherRegister
|
||||
};
|
||||
|
||||
enum RegisterFormat
|
||||
{
|
||||
CharacterFormat,
|
||||
HexadecimalFormat,
|
||||
DecimalFormat,
|
||||
OctalFormat,
|
||||
BinaryFormat
|
||||
};
|
||||
|
||||
class RegisterValue
|
||||
{
|
||||
public:
|
||||
@@ -73,7 +82,7 @@ public:
|
||||
void operator=(const QByteArray &ba);
|
||||
bool operator==(const RegisterValue &other);
|
||||
bool operator!=(const RegisterValue &other) { return !operator==(other); }
|
||||
QByteArray toByteArray(int base, RegisterKind kind, int size) const;
|
||||
QByteArray toByteArray(RegisterKind kind, int size, RegisterFormat format) const;
|
||||
RegisterValue subValue(int size, int index) const;
|
||||
|
||||
union {
|
||||
@@ -116,7 +125,7 @@ public:
|
||||
|
||||
void updateRegister(const Register ®);
|
||||
|
||||
void setNumberBase(const QByteArray &name, int base);
|
||||
void setNumberFormat(const QByteArray &name, RegisterFormat format);
|
||||
void commitUpdates() { emit layoutChanged(); }
|
||||
RegisterMap registerMap() const;
|
||||
|
||||
|
@@ -66,11 +66,20 @@ public:
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
IntegerWatchLineEdit *lineEdit = new IntegerWatchLineEdit(parent);
|
||||
const int base = index.data(RegisterNumberBaseRole).toInt();
|
||||
const RegisterFormat format = RegisterFormat(index.data(RegisterFormatRole).toInt());
|
||||
const bool big = index.data(RegisterIsBigRole).toBool();
|
||||
// Big integers are assumed to be hexadecimal.
|
||||
int base = 16;
|
||||
if (!big) {
|
||||
if (format == DecimalFormat)
|
||||
base = 10;
|
||||
else if (format == OctalFormat)
|
||||
base = 8;
|
||||
else if (format == BinaryFormat)
|
||||
base = 2;
|
||||
}
|
||||
lineEdit->setBigInt(big);
|
||||
lineEdit->setBase(big ? 16 : base);
|
||||
lineEdit->setBase(base);
|
||||
lineEdit->setSigned(false);
|
||||
lineEdit->setAlignment(Qt::AlignRight);
|
||||
lineEdit->setFrame(false);
|
||||
@@ -91,9 +100,9 @@ public:
|
||||
return;
|
||||
IntegerWatchLineEdit *lineEdit = qobject_cast<IntegerWatchLineEdit*>(editor);
|
||||
QTC_ASSERT(lineEdit, return);
|
||||
const int base = index.data(RegisterNumberBaseRole).toInt();
|
||||
const RegisterFormat format = RegisterFormat(index.data(RegisterFormatRole).toInt());
|
||||
QString value = lineEdit->text();
|
||||
if (base == 16 && !value.startsWith(QLatin1String("0x")))
|
||||
if (format == HexadecimalFormat && !value.startsWith(QLatin1String("0x")))
|
||||
value.insert(0, QLatin1String("0x"));
|
||||
currentEngine()->setRegisterValue(index.data(RegisterNameRole).toByteArray(), value);
|
||||
}
|
||||
@@ -206,19 +215,19 @@ void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev)
|
||||
}
|
||||
menu.addSeparator();
|
||||
|
||||
const int base = idx.data(RegisterNumberBaseRole).toInt();
|
||||
const RegisterFormat format = RegisterFormat(idx.data(RegisterFormatRole).toInt());
|
||||
QAction *act16 = menu.addAction(tr("Hexadecimal"));
|
||||
act16->setCheckable(true);
|
||||
act16->setChecked(base == 16);
|
||||
act16->setChecked(format == HexadecimalFormat);
|
||||
QAction *act10 = menu.addAction(tr("Decimal"));
|
||||
act10->setCheckable(true);
|
||||
act10->setChecked(base == 10);
|
||||
act10->setChecked(format == DecimalFormat);
|
||||
QAction *act8 = menu.addAction(tr("Octal"));
|
||||
act8->setCheckable(true);
|
||||
act8->setChecked(base == 8);
|
||||
act8->setChecked(format == OctalFormat);
|
||||
QAction *act2 = menu.addAction(tr("Binary"));
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(base == 2);
|
||||
act2->setChecked(format == BinaryFormat);
|
||||
|
||||
menu.addSeparator();
|
||||
menu.addAction(action(SettingsDialog));
|
||||
@@ -252,13 +261,13 @@ void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev)
|
||||
} else if (act == actShowDisassemblerAt) {
|
||||
engine->openDisassemblerView(Location(address));
|
||||
} else if (act == act16)
|
||||
handler->setNumberBase(registerName, 16);
|
||||
handler->setNumberFormat(registerName, HexadecimalFormat);
|
||||
else if (act == act10)
|
||||
handler->setNumberBase(registerName, 10);
|
||||
handler->setNumberFormat(registerName, DecimalFormat);
|
||||
else if (act == act8)
|
||||
handler->setNumberBase(registerName, 8);
|
||||
handler->setNumberFormat(registerName, OctalFormat);
|
||||
else if (act == act2)
|
||||
handler->setNumberBase(registerName, 2);
|
||||
handler->setNumberFormat(registerName, BinaryFormat);
|
||||
}
|
||||
|
||||
void RegisterTreeView::reloadRegisters()
|
||||
|
Reference in New Issue
Block a user