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
}
// Return hexadecimal pointer value from a CDB pointer value
// which look like "0x000032a" or "0x00000000`0250124a" on 64-bit systems.
static bool inline getPointerValue(QString stringValue, quint64 *value)
// which look like "0x000032a" or "0x00000000`0250124a" or
// "0x1`0250124a" on 64-bit systems.
static bool inline getUnsignedHexValue(QString stringValue, quint64 *value)
{
*value = 0;
if (!stringValue.startsWith(QLatin1String("0x")))
return false;
stringValue.remove(0, 2);
// Remove 64bit separator
if (stringValue.size() > 8 && stringValue.at(8) == QLatin1Char('`'))
stringValue.remove(8, 1);
if (stringValue.size() > 9) {
const int sepPos = stringValue.size() - 9;
if (stringValue.at(sepPos) == QLatin1Char('`'))
stringValue.remove(sepPos, 1);
}
bool ok;
*value = stringValue.toULongLong(&ok, 16);
return ok;
......@@ -427,7 +431,7 @@ static inline bool isNullPointer(const WatchData &wd)
if (blankPos != -1)
stringValue.truncate(blankPos);
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
......@@ -445,11 +449,21 @@ static inline QString removeInnerTemplateType(QString 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 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
......@@ -481,7 +495,7 @@ WatchData CdbSymbolGroupContext::watchDataAt(unsigned long index) const
return wd;
}
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
// Figure out children. The SubElement is only a guess unless the symbol,
// 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)
// Get pointer value of symbol group ("0xAAB")
// 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);
return getPointerValue(stringValue, value);
return getUnsignedHexValue(stringValue, value);
}
int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
......@@ -756,7 +770,7 @@ int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
if (!getIntValue(m_symbolGroup, sizeIndex, &size))
return 4;
quint64 array;
if (!getPointerValue(m_symbolGroup, arrayIndex, &array))
if (!getUnsignedHexValue(m_symbolGroup, arrayIndex, &array))
return 5;
// Fetch
const bool truncated = size > maxLength;
......
......@@ -588,21 +588,32 @@ QString niceType(const QString typeIn)
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,
int individualFormat, int typeFormat)
{
if (isIntType(data.type)) {
int format = individualFormat == -1 ? typeFormat : individualFormat;
int value = data.value.toInt();
if (format == HexadecimalFormat)
return ("(hex) ") + QString::number(value, 16);
if (format == BinaryFormat)
return ("(bin) ") + QString::number(value, 2);
if (format == OctalFormat)
return ("(oct) ") + QString::number(value, 8);
return data.value;
const int format = individualFormat == -1 ? typeFormat : individualFormat;
if (format <= 0)
return data.value;
if (data.type.contains(QLatin1String("unsigned"))) {
return reformatInteger(data.value.toULongLong(), format);
} else {
return reformatInteger(data.value.toLongLong(), format);
}
}
return data.value;
}
......@@ -769,15 +780,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
break;
case TypeFormatRole:
return m_handler->m_typeFormats[data.type];
case IndividualFormatRole: {
int format = m_handler->m_individualFormats[data.iname];
if (format == -1)
return m_handler->m_typeFormats[data.type];
return format;
}
return m_handler->m_typeFormats.value(data.type, -1);
case IndividualFormatRole:
return m_handler->m_individualFormats.value(data.iname, -1);
case AddressRole: {
if (!data.addr.isEmpty())
return data.addr;
......@@ -807,8 +812,13 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
}
} else if (role == TypeFormatRole) {
m_handler->setFormat(data.type, value.toInt());
} else if (role == IndividualFormatRole) {
m_handler->m_individualFormats[data.iname] = value.toInt();
} else if (role == IndividualFormatRole) {
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);
return true;
......@@ -1373,9 +1383,12 @@ void WatchHandler::saveTypeFormats()
QHashIterator<QString, int> it(m_typeFormats);
while (it.hasNext()) {
it.next();
QString key = it.key().trimmed();
if (!key.isEmpty())
typeFormats.insert(key, it.value());
const int format = it.value();
if (format != DecimalFormat) {
const QString key = it.key().trimmed();
if (!key.isEmpty())
typeFormats.insert(key, format);
}
}
m_manager->setSessionValue("DefaultFormats", QVariant(typeFormats));
}
......
......@@ -542,8 +542,13 @@ bool isIntType(const QString &type)
<< QLatin1String("long") << QLatin1String("bool")
<< QLatin1String("signed char") << QLatin1String("unsigned")
<< QLatin1String("unsigned char") << QLatin1String("unsigned long")
<< QLatin1String("long long") << QLatin1String("unsigned long long");
return type.endsWith(QLatin1String(" int")) || types.contains(type);
<< QLatin1String("long long") << QLatin1String("unsigned long long")
<< 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)
......
......@@ -210,36 +210,40 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QStringList alternativeFormats =
model()->data(mi0, TypeFormatListRole).toStringList();
int typeFormat =
model()->data(mi0, TypeFormatRole).toInt();
int individualFormat =
model()->data(mi0, IndividualFormatRole).toInt();
const int typeFormat = qMax(int(DecimalFormat), model()->data(mi0, TypeFormatRole).toInt());
const int individualFormat = model()->data(mi0, IndividualFormatRole).toInt();
const int effectiveIndividualFormat = individualFormat == -1 ? typeFormat : individualFormat;
QMenu typeFormatMenu;
QMenu individualFormatMenu;
QList<QAction *> typeFormatActions;
QList<QAction *> individualFormatActions;
QAction *clearIndividualFormatAction = 0;
if (idx.isValid()) {
typeFormatMenu.setTitle(tr("Change format for type '%1'").arg(type));
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()) {
typeFormatMenu.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 {
typeFormatMenu.setTitle(tr("Change format for type"));
......@@ -316,6 +320,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
m_grabbing = true;
} else if (act == actClearCodeModelSnapshot) {
m_manager->clearCppCodeModelSnapshot();
} else if (clearIndividualFormatAction && act == clearIndividualFormatAction) {
model()->setData(mi1, -1, IndividualFormatRole);
} else {
for (int i = 0; i != alternativeFormats.size(); ++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