Commit 2b23ea2a authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Debugger/CDB: Windows 64 integer handling.



Convert CDB unsigned integer values should they appear in hex,
make format flexible.
Use int64 for reformatting integers to be able to accommodate
64 bit values on Windows 64. Add some more integer types.
Do not save decimal type formats. Add menu option to clear
individual formatting. Do not use map[] to query the type formats
(inserting 0 everywhere as a side effect).
Reviewed-by: default avatarOswald Buddenhagen <oswald.buddenhagen@nokia.com>
parent 32dd4567
...@@ -402,16 +402,20 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const ...@@ -402,16 +402,20 @@ QString CdbSymbolGroupContext::symbolINameAt(unsigned long index) const
} }
// Return hexadecimal pointer value from a CDB pointer value // Return hexadecimal pointer value from a CDB pointer value
// which look like "0x000032a" or "0x00000000`0250124a" on 64-bit systems. // which look like "0x000032a" or "0x00000000`0250124a" or
static bool inline getPointerValue(QString stringValue, quint64 *value) // "0x1`0250124a" on 64-bit systems.
static bool inline getUnsignedHexValue(QString stringValue, quint64 *value)
{ {
*value = 0; *value = 0;
if (!stringValue.startsWith(QLatin1String("0x"))) if (!stringValue.startsWith(QLatin1String("0x")))
return false; return false;
stringValue.remove(0, 2); stringValue.remove(0, 2);
// Remove 64bit separator // Remove 64bit separator
if (stringValue.size() > 8 && stringValue.at(8) == QLatin1Char('`')) if (stringValue.size() > 9) {
stringValue.remove(8, 1); const int sepPos = stringValue.size() - 9;
if (stringValue.at(sepPos) == QLatin1Char('`'))
stringValue.remove(sepPos, 1);
}
bool ok; bool ok;
*value = stringValue.toULongLong(&ok, 16); *value = stringValue.toULongLong(&ok, 16);
return ok; return ok;
...@@ -427,7 +431,7 @@ static inline bool isNullPointer(const WatchData &wd) ...@@ -427,7 +431,7 @@ static inline bool isNullPointer(const WatchData &wd)
if (blankPos != -1) if (blankPos != -1)
stringValue.truncate(blankPos); stringValue.truncate(blankPos);
quint64 value; quint64 value;
return getPointerValue(stringValue, &value) && value == 0u; return getUnsignedHexValue(stringValue, &value) && value == 0u;
} }
// Fix a symbol group value. It is set to the class type for // Fix a symbol group value. It is set to the class type for
...@@ -445,11 +449,21 @@ static inline QString removeInnerTemplateType(QString value) ...@@ -445,11 +449,21 @@ static inline QString removeInnerTemplateType(QString value)
return value; return value;
} }
static inline QString fixValue(const QString &value) // Fix display values: Pass through strings, convert unsigned integers
// to decimal ('0x5454`fedf'), remove inner templates from
// "0x4343 class list<>".
static inline QString fixValue(const QString &value, const QString &type)
{ {
if (value.size() < 20 || value.endsWith(QLatin1Char('"'))) if (value.endsWith(QLatin1Char('"'))) // Pass through strings
return value; return value;
return removeInnerTemplateType(value); const int size = value.size();
// Unsigned hex numbers
if (isIntType(type) && (size > 2 && value.at(1) == QLatin1Char('x'))) {
quint64 intValue;
if (getUnsignedHexValue(value, &intValue))
return QString::number(intValue);
}
return size < 20 ? value : removeInnerTemplateType(value);
} }
WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
...@@ -481,7 +495,7 @@ WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const ...@@ -481,7 +495,7 @@ WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
return wd; return wd;
} }
const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index); const QString value = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
wd.setValue(fixValue(value)); wd.setValue(fixValue(value, type));
wd.setChildrenNeeded(); // compensate side effects of above setters wd.setChildrenNeeded(); // compensate side effects of above setters
// Figure out children. The SubElement is only a guess unless the symbol, // Figure out children. The SubElement is only a guess unless the symbol,
// is expanded, so, we leave this as a guess for later updates. // is expanded, so, we leave this as a guess for later updates.
...@@ -729,10 +743,10 @@ static inline bool getIntValue(CIDebugSymbolGroup *sg, int index, int *value) ...@@ -729,10 +743,10 @@ static inline bool getIntValue(CIDebugSymbolGroup *sg, int index, int *value)
// Get pointer value of symbol group ("0xAAB") // Get pointer value of symbol group ("0xAAB")
// Note that this is on "00000000`0250124a" on 64bit systems. // Note that this is on "00000000`0250124a" on 64bit systems.
static inline bool getPointerValue(CIDebugSymbolGroup *sg, int index, quint64 *value) static inline bool getUnsignedHexValue(CIDebugSymbolGroup *sg, int index, quint64 *value)
{ {
const QString stringValue = getSymbolString(sg, &IDebugSymbolGroup2::GetSymbolValueTextWide, index); const QString stringValue = getSymbolString(sg, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
return getPointerValue(stringValue, value); return getUnsignedHexValue(stringValue, value);
} }
int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd) int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
...@@ -756,7 +770,7 @@ int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd) ...@@ -756,7 +770,7 @@ int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
if (!getIntValue(m_symbolGroup, sizeIndex, &size)) if (!getIntValue(m_symbolGroup, sizeIndex, &size))
return 4; return 4;
quint64 array; quint64 array;
if (!getPointerValue(m_symbolGroup, arrayIndex, &array)) if (!getUnsignedHexValue(m_symbolGroup, arrayIndex, &array))
return 5; return 5;
// Fetch // Fetch
const bool truncated = size > maxLength; const bool truncated = size > maxLength;
......
...@@ -588,21 +588,32 @@ QString niceType(const QString typeIn) ...@@ -588,21 +588,32 @@ QString niceType(const QString typeIn)
return type; return type;
} }
template <class IntType> QString reformatInteger(IntType value, int format)
{
switch (format) {
case HexadecimalFormat:
return ("(hex) ") + QString::number(value, 16);
case BinaryFormat:
return ("(bin) ") + QString::number(value, 2);
case OctalFormat:
return ("(oct) ") + QString::number(value, 8);
}
return QString::number(value); // not reached
}
static QString formattedValue(const WatchData &data, static QString formattedValue(const WatchData &data,
int individualFormat, int typeFormat) int individualFormat, int typeFormat)
{ {
if (isIntType(data.type)) { if (isIntType(data.type)) {
int format = individualFormat == -1 ? typeFormat : individualFormat; const int format = individualFormat == -1 ? typeFormat : individualFormat;
int value = data.value.toInt(); if (format <= 0)
if (format == HexadecimalFormat) return data.value;
return ("(hex) ") + QString::number(value, 16); if (data.type.contains(QLatin1String("unsigned"))) {
if (format == BinaryFormat) return reformatInteger(data.value.toULongLong(), format);
return ("(bin) ") + QString::number(value, 2); } else {
if (format == OctalFormat) return reformatInteger(data.value.toLongLong(), format);
return ("(oct) ") + QString::number(value, 8); }
return data.value;
} }
return data.value; return data.value;
} }
...@@ -769,15 +780,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const ...@@ -769,15 +780,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
break; break;
case TypeFormatRole: case TypeFormatRole:
return m_handler->m_typeFormats[data.type]; return m_handler->m_typeFormats.value(data.type, -1);
case IndividualFormatRole:
case IndividualFormatRole: { return m_handler->m_individualFormats.value(data.iname, -1);
int format = m_handler->m_individualFormats[data.iname];
if (format == -1)
return m_handler->m_typeFormats[data.type];
return format;
}
case AddressRole: { case AddressRole: {
if (!data.addr.isEmpty()) if (!data.addr.isEmpty())
return data.addr; return data.addr;
...@@ -807,8 +812,13 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro ...@@ -807,8 +812,13 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
} }
} else if (role == TypeFormatRole) { } else if (role == TypeFormatRole) {
m_handler->setFormat(data.type, value.toInt()); m_handler->setFormat(data.type, value.toInt());
} else if (role == IndividualFormatRole) { } else if (role == IndividualFormatRole) {
m_handler->m_individualFormats[data.iname] = value.toInt(); const int format = value.toInt();
if (format == -1) {
m_handler->m_individualFormats.remove(data.iname);
} else {
m_handler->m_individualFormats[data.iname] = format;
}
} }
emit dataChanged(index, index); emit dataChanged(index, index);
return true; return true;
...@@ -1373,9 +1383,12 @@ void WatchHandler::saveTypeFormats() ...@@ -1373,9 +1383,12 @@ void WatchHandler::saveTypeFormats()
QHashIterator<QString, int> it(m_typeFormats); QHashIterator<QString, int> it(m_typeFormats);
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
QString key = it.key().trimmed(); const int format = it.value();
if (!key.isEmpty()) if (format != DecimalFormat) {
typeFormats.insert(key, it.value()); const QString key = it.key().trimmed();
if (!key.isEmpty())
typeFormats.insert(key, format);
}
} }
m_manager->setSessionValue("DefaultFormats", QVariant(typeFormats)); m_manager->setSessionValue("DefaultFormats", QVariant(typeFormats));
} }
......
...@@ -542,8 +542,13 @@ bool isIntType(const QString &type) ...@@ -542,8 +542,13 @@ bool isIntType(const QString &type)
<< QLatin1String("long") << QLatin1String("bool") << QLatin1String("long") << QLatin1String("bool")
<< QLatin1String("signed char") << QLatin1String("unsigned") << QLatin1String("signed char") << QLatin1String("unsigned")
<< QLatin1String("unsigned char") << QLatin1String("unsigned long") << QLatin1String("unsigned char") << QLatin1String("unsigned long")
<< QLatin1String("long long") << QLatin1String("unsigned long long"); << QLatin1String("long long") << QLatin1String("unsigned long long")
return type.endsWith(QLatin1String(" int")) || types.contains(type); << QLatin1String("qint16") << QLatin1String("quint16")
<< QLatin1String("qint32") << QLatin1String("quint32")
<< QLatin1String("qint64") << QLatin1String("quint64");
return type.endsWith(QLatin1String(" int"))
|| type.endsWith(QLatin1String(" int64"))
|| types.contains(type);
} }
bool isSymbianIntType(const QString &type) bool isSymbianIntType(const QString &type)
......
...@@ -210,36 +210,40 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) ...@@ -210,36 +210,40 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QStringList alternativeFormats = QStringList alternativeFormats =
model()->data(mi0, TypeFormatListRole).toStringList(); model()->data(mi0, TypeFormatListRole).toStringList();
int typeFormat = const int typeFormat = qMax(int(DecimalFormat), model()->data(mi0, TypeFormatRole).toInt());
model()->data(mi0, TypeFormatRole).toInt(); const int individualFormat = model()->data(mi0, IndividualFormatRole).toInt();
int individualFormat = const int effectiveIndividualFormat = individualFormat == -1 ? typeFormat : individualFormat;
model()->data(mi0, IndividualFormatRole).toInt();
QMenu typeFormatMenu; QMenu typeFormatMenu;
QMenu individualFormatMenu; QMenu individualFormatMenu;
QList<QAction *> typeFormatActions; QList<QAction *> typeFormatActions;
QList<QAction *> individualFormatActions; QList<QAction *> individualFormatActions;
QAction *clearIndividualFormatAction = 0;
if (idx.isValid()) { if (idx.isValid()) {
typeFormatMenu.setTitle(tr("Change format for type '%1'").arg(type)); typeFormatMenu.setTitle(tr("Change format for type '%1'").arg(type));
individualFormatMenu.setTitle(tr("Change format for expression '%1'").arg(exp)); individualFormatMenu.setTitle(tr("Change format for expression '%1'").arg(exp));
for (int i = 0; i != alternativeFormats.size(); ++i) {
const QString format = alternativeFormats.at(i);
QAction *act = new QAction(format, &typeFormatMenu);
act->setCheckable(true);
if (i == typeFormat)
act->setChecked(true);
typeFormatMenu.addAction(act);
typeFormatActions.append(act);
act = new QAction(format, &individualFormatMenu);
act->setCheckable(true);
if (i == individualFormat)
act->setChecked(true);
individualFormatMenu.addAction(act);
individualFormatActions.append(act);
}
if (alternativeFormats.isEmpty()) { if (alternativeFormats.isEmpty()) {
typeFormatMenu.setEnabled(false); typeFormatMenu.setEnabled(false);
individualFormatMenu.setEnabled(false); individualFormatMenu.setEnabled(false);
} else {
clearIndividualFormatAction = individualFormatMenu.addAction(tr("Clear"));
clearIndividualFormatAction->setEnabled(individualFormat != -1);
individualFormatMenu.addSeparator();
for (int i = 0; i != alternativeFormats.size(); ++i) {
const QString format = alternativeFormats.at(i);
QAction *act = new QAction(format, &typeFormatMenu);
act->setCheckable(true);
if (i == typeFormat)
act->setChecked(true);
typeFormatMenu.addAction(act);
typeFormatActions.append(act);
act = new QAction(format, &individualFormatMenu);
act->setCheckable(true);
if (i == effectiveIndividualFormat)
act->setChecked(true);
individualFormatMenu.addAction(act);
individualFormatActions.append(act);
}
} }
} else { } else {
typeFormatMenu.setTitle(tr("Change format for type")); typeFormatMenu.setTitle(tr("Change format for type"));
...@@ -316,6 +320,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev) ...@@ -316,6 +320,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
m_grabbing = true; m_grabbing = true;
} else if (act == actClearCodeModelSnapshot) { } else if (act == actClearCodeModelSnapshot) {
m_manager->clearCppCodeModelSnapshot(); m_manager->clearCppCodeModelSnapshot();
} else if (clearIndividualFormatAction && act == clearIndividualFormatAction) {
model()->setData(mi1, -1, IndividualFormatRole);
} else { } else {
for (int i = 0; i != alternativeFormats.size(); ++i) { for (int i = 0; i != alternativeFormats.size(); ++i) {
if (act == typeFormatActions.at(i)) if (act == typeFormatActions.at(i))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment