forked from qt-creator/qt-creator
Debugger: Sanitize Datatypes, part 3: Address of watch items.
Use a quint64 as address. Split apart special handling of QAbstractItemModels of old shared-library based dumpers (passing '$'+ special expression as address) into separate dumperFlags QByteArray.
This commit is contained in:
@@ -623,7 +623,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpTypeI(const WatchData &wd, bool
|
|||||||
*errorMessage = msgNotHandled(wd.type);
|
*errorMessage = msgNotHandled(wd.type);
|
||||||
return DumpNotHandled;
|
return DumpNotHandled;
|
||||||
}
|
}
|
||||||
if (wd.addr.isEmpty()) {
|
if (wd.address == 0) {
|
||||||
*errorMessage = QString::fromLatin1("Address is missing for '%1' (%2).")
|
*errorMessage = QString::fromLatin1("Address is missing for '%1' (%2).")
|
||||||
.arg(QString::fromUtf8(wd.exp)).arg(QString::fromUtf8(wd.type));
|
.arg(QString::fromUtf8(wd.exp)).arg(QString::fromUtf8(wd.type));
|
||||||
return DumpNotHandled;
|
return DumpNotHandled;
|
||||||
@@ -690,7 +690,7 @@ CdbDumperHelper::DumpExecuteResult
|
|||||||
m_helper.evaluationParameters(wd, td, QtDumperHelper::CdbDebugger, &inBuffer, &extraParameters);
|
m_helper.evaluationParameters(wd, td, QtDumperHelper::CdbDebugger, &inBuffer, &extraParameters);
|
||||||
QString callCmd;
|
QString callCmd;
|
||||||
QTextStream str(&callCmd);
|
QTextStream str(&callCmd);
|
||||||
str << ".call " << m_dumpObjectSymbol << "(2,0," << wd.addr << ',' << (dumpChildren ? 1 : 0);
|
str << ".call " << m_dumpObjectSymbol << "(2,0," << wd.hexAddress() << ',' << (dumpChildren ? 1 : 0);
|
||||||
foreach(const QByteArray &e, extraParameters)
|
foreach(const QByteArray &e, extraParameters)
|
||||||
str << ',' << QString::fromUtf8(e);
|
str << ',' << QString::fromUtf8(e);
|
||||||
str << ')';
|
str << ')';
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ static inline void fixDumperResult(const WatchData &source,
|
|||||||
it->source |= CdbSymbolGroupContext::ChildrenKnownBit;
|
it->source |= CdbSymbolGroupContext::ChildrenKnownBit;
|
||||||
// Cannot dump items with missing addresses or missing types
|
// Cannot dump items with missing addresses or missing types
|
||||||
const bool typeFixed = fixDumperType(&wd); // Order of evaluation!
|
const bool typeFixed = fixDumperType(&wd); // Order of evaluation!
|
||||||
if ((wd.addr.isEmpty() && wd.isSomethingNeeded()) || typeFixed) {
|
if ((wd.address == 0 && wd.isSomethingNeeded()) || typeFixed) {
|
||||||
wd.setHasChildren(false);
|
wd.setHasChildren(false);
|
||||||
wd.setAllUnneeded();
|
wd.setAllUnneeded();
|
||||||
} else {
|
} else {
|
||||||
@@ -239,7 +239,7 @@ bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QSt
|
|||||||
const QByteArray type = stripPointerType(wd.type);
|
const QByteArray type = stripPointerType(wd.type);
|
||||||
WatchData derefedWd;
|
WatchData derefedWd;
|
||||||
derefedWd.setType(type);
|
derefedWd.setType(type);
|
||||||
derefedWd.setAddress(hexAddrS.toLatin1());
|
derefedWd.setHexAddress(hexAddrS.toAscii());
|
||||||
derefedWd.name = QString(QLatin1Char('*'));
|
derefedWd.name = QString(QLatin1Char('*'));
|
||||||
derefedWd.iname = wd.iname + ".*";
|
derefedWd.iname = wd.iname + ".*";
|
||||||
derefedWd.source = OwnerDumper | CdbSymbolGroupContext::ChildrenKnownBit;
|
derefedWd.source = OwnerDumper | CdbSymbolGroupContext::ChildrenKnownBit;
|
||||||
@@ -373,7 +373,7 @@ unsigned CdbSymbolGroupContext::watchDataAt(unsigned long index, WatchData *wd)
|
|||||||
const unsigned rc = dumpValue(index, &iname, &(wd->name), &address,
|
const unsigned rc = dumpValue(index, &iname, &(wd->name), &address,
|
||||||
&typeId, &type, &value);
|
&typeId, &type, &value);
|
||||||
wd->exp = wd->iname = iname.toLatin1();
|
wd->exp = wd->iname = iname.toLatin1();
|
||||||
wd->setAddress("0x" + QByteArray::number(address, 16));
|
wd->setAddress(address);
|
||||||
wd->setType(type.toUtf8(), false);
|
wd->setType(type.toUtf8(), false);
|
||||||
if (rc & OutOfScope) {
|
if (rc & OutOfScope) {
|
||||||
wd->setError(WatchData::msgNotInScope());
|
wd->setError(WatchData::msgNotInScope());
|
||||||
|
|||||||
@@ -183,8 +183,8 @@ void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChild
|
|||||||
//int protocol = isDisplayedIName(data.iname) ? 3 : 2;
|
//int protocol = isDisplayedIName(data.iname) ? 3 : 2;
|
||||||
|
|
||||||
QByteArray addr;
|
QByteArray addr;
|
||||||
if (data.addr.startsWith("0x"))
|
if (data.address)
|
||||||
addr = "(void*)" + data.addr;
|
addr = "(void*)" + data.hexAddress();
|
||||||
else if (data.exp.isEmpty()) // happens e.g. for QAbstractItem
|
else if (data.exp.isEmpty()) // happens e.g. for QAbstractItem
|
||||||
addr = QByteArray(1, '0');
|
addr = QByteArray(1, '0');
|
||||||
else
|
else
|
||||||
@@ -220,8 +220,8 @@ void GdbEngine::createGdbVariableClassic(const WatchData &data)
|
|||||||
}
|
}
|
||||||
postCommand("-var-delete \"" + data.iname + '"', WatchUpdate);
|
postCommand("-var-delete \"" + data.iname + '"', WatchUpdate);
|
||||||
QByteArray exp = data.exp;
|
QByteArray exp = data.exp;
|
||||||
if (exp.isEmpty() && data.addr.startsWith("0x"))
|
if (exp.isEmpty() && data.address)
|
||||||
exp = "*(" + gdbQuoteTypes(data.type) + "*)" + data.addr;
|
exp = "*(" + gdbQuoteTypes(data.type) + "*)" + data.hexAddress();
|
||||||
QVariant val = QVariant::fromValue<WatchData>(data);
|
QVariant val = QVariant::fromValue<WatchData>(data);
|
||||||
postCommand("-var-create \"" + data.iname + "\" * \"" + exp + '"',
|
postCommand("-var-create \"" + data.iname + "\" * \"" + exp + '"',
|
||||||
WatchUpdate, CB(handleVarCreate), val);
|
WatchUpdate, CB(handleVarCreate), val);
|
||||||
@@ -474,8 +474,13 @@ void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
|
|||||||
data1.name = _("[%1]").arg(i);
|
data1.name = _("[%1]").arg(i);
|
||||||
data1.type = data.type.left(data.type.size() - 4);
|
data1.type = data.type.left(data.type.size() - 4);
|
||||||
data1.iname = data.iname + '.' + QByteArray::number(i);
|
data1.iname = data.iname + '.' + QByteArray::number(i);
|
||||||
data1.addr = list.at(i);
|
const QByteArray &addressSpec = list.at(i);
|
||||||
data1.exp = "((" + gdbQuoteTypes(data1.type) + "*)" + data1.addr + ')';
|
if (addressSpec.startsWith("0x")) {
|
||||||
|
data.setHexAddress(addressSpec);
|
||||||
|
} else {
|
||||||
|
data.dumperFlags = addressSpec; // Item model dumpers pull tricks
|
||||||
|
}
|
||||||
|
data1.exp = "((" + gdbQuoteTypes(data1.type) + "*)" + addressSpec + ')';
|
||||||
data1.setHasChildren(false);
|
data1.setHasChildren(false);
|
||||||
data1.setValueNeeded();
|
data1.setValueNeeded();
|
||||||
QByteArray cmd = "qdumpqstring (" + data1.exp + ')';
|
QByteArray cmd = "qdumpqstring (" + data1.exp + ')';
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ namespace Internal {
|
|||||||
|
|
||||||
WatchData::WatchData() :
|
WatchData::WatchData() :
|
||||||
editformat(0),
|
editformat(0),
|
||||||
|
address(0),
|
||||||
hasChildren(false),
|
hasChildren(false),
|
||||||
generation(-1),
|
generation(-1),
|
||||||
valueEnabled(true),
|
valueEnabled(true),
|
||||||
@@ -42,7 +43,7 @@ bool WatchData::isEqual(const WatchData &other) const
|
|||||||
&& type == other.type
|
&& type == other.type
|
||||||
&& displayedType == other.displayedType
|
&& displayedType == other.displayedType
|
||||||
&& variable == other.variable
|
&& variable == other.variable
|
||||||
&& addr == other.addr
|
&& address == other.address
|
||||||
&& framekey == other.framekey
|
&& framekey == other.framekey
|
||||||
&& hasChildren == other.hasChildren
|
&& hasChildren == other.hasChildren
|
||||||
&& valueEnabled == other.valueEnabled
|
&& valueEnabled == other.valueEnabled
|
||||||
@@ -145,9 +146,22 @@ void WatchData::setType(const QByteArray &str, bool guessChildrenFromType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WatchData::setAddress(const QByteArray &a)
|
void WatchData::setAddress(const quint64 &a)
|
||||||
{
|
{
|
||||||
addr = a;
|
address = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WatchData::setHexAddress(const QByteArray &a)
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
const qint64 av = a.toULongLong(&ok, 16);
|
||||||
|
if (ok) {
|
||||||
|
address = av;
|
||||||
|
} else {
|
||||||
|
qWarning("WatchData::setHexAddress(): Failed to parse address value '%s' for '%s', '%s'",
|
||||||
|
a.constData(), iname.constData(), type.constData());
|
||||||
|
address = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString WatchData::toString() const
|
QString WatchData::toString() const
|
||||||
@@ -162,8 +176,11 @@ QString WatchData::toString() const
|
|||||||
str << "name=\"" << name << doubleQuoteComma;
|
str << "name=\"" << name << doubleQuoteComma;
|
||||||
if (error)
|
if (error)
|
||||||
str << "error,";
|
str << "error,";
|
||||||
if (!addr.isEmpty())
|
if (address) {
|
||||||
str << "addr=\"" << addr << doubleQuoteComma;
|
str.setIntegerBase(16);
|
||||||
|
str << "addr=\"0x" << address << doubleQuoteComma;
|
||||||
|
str.setIntegerBase(10);
|
||||||
|
}
|
||||||
if (!exp.isEmpty())
|
if (!exp.isEmpty())
|
||||||
str << "exp=\"" << exp << doubleQuoteComma;
|
str << "exp=\"" << exp << doubleQuoteComma;
|
||||||
|
|
||||||
@@ -179,6 +196,9 @@ QString WatchData::toString() const
|
|||||||
str << "editvalue=\"<...>\",";
|
str << "editvalue=\"<...>\",";
|
||||||
// str << "editvalue=\"" << editvalue << doubleQuoteComma;
|
// str << "editvalue=\"" << editvalue << doubleQuoteComma;
|
||||||
|
|
||||||
|
if (!dumperFlags.isEmpty())
|
||||||
|
str << "dumperFlags=\"" << dumperFlags << doubleQuoteComma;
|
||||||
|
|
||||||
if (isTypeNeeded())
|
if (isTypeNeeded())
|
||||||
str << "type=<needed>,";
|
str << "type=<needed>,";
|
||||||
if (isTypeKnown() && !type.isEmpty())
|
if (isTypeKnown() && !type.isEmpty())
|
||||||
@@ -234,7 +254,8 @@ QString WatchData::toToolTip() const
|
|||||||
val += QCoreApplication::translate("Debugger::Internal::WatchHandler", " ... <cut off>");
|
val += QCoreApplication::translate("Debugger::Internal::WatchHandler", " ... <cut off>");
|
||||||
}
|
}
|
||||||
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Value"), val);
|
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Value"), val);
|
||||||
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Object Address"), addr);
|
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Object Address"),
|
||||||
|
QString::fromAscii(hexAddress()));
|
||||||
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Internal ID"), iname);
|
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Internal ID"), iname);
|
||||||
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Generation"),
|
formatToolTipRow(str, QCoreApplication::translate("Debugger::Internal::WatchHandler", "Generation"),
|
||||||
QString::number(generation));
|
QString::number(generation));
|
||||||
@@ -267,13 +288,12 @@ QString WatchData::shadowedName(const QString &name, int seen)
|
|||||||
|
|
||||||
quint64 WatchData::coreAddress() const
|
quint64 WatchData::coreAddress() const
|
||||||
{
|
{
|
||||||
if (!addr.isEmpty()) {
|
return address;
|
||||||
bool ok;
|
}
|
||||||
const quint64 address = addr.toULongLong(&ok, 16);
|
|
||||||
if (ok)
|
QByteArray WatchData::hexAddress() const
|
||||||
return address;
|
{
|
||||||
}
|
return address ? (QByteArray("0x") + QByteArray::number(address, 16)) : QByteArray();
|
||||||
return quint64(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -66,7 +66,8 @@ public:
|
|||||||
void setType(const QByteArray &, bool guessChildrenFromType = true);
|
void setType(const QByteArray &, bool guessChildrenFromType = true);
|
||||||
void setValueToolTip(const QString &);
|
void setValueToolTip(const QString &);
|
||||||
void setError(const QString &);
|
void setError(const QString &);
|
||||||
void setAddress(const QByteArray &);
|
void setAddress(const quint64 &);
|
||||||
|
void setHexAddress(const QByteArray &a);
|
||||||
|
|
||||||
bool isSomethingNeeded() const { return state & NeededMask; }
|
bool isSomethingNeeded() const { return state & NeededMask; }
|
||||||
void setAllNeeded() { state = NeededMask; }
|
void setAllNeeded() { state = NeededMask; }
|
||||||
@@ -102,6 +103,7 @@ public:
|
|||||||
|
|
||||||
bool isEqual(const WatchData &other) const;
|
bool isEqual(const WatchData &other) const;
|
||||||
quint64 coreAddress() const;
|
quint64 coreAddress() const;
|
||||||
|
QByteArray hexAddress() const;
|
||||||
|
|
||||||
static QString msgNotInScope();
|
static QString msgNotInScope();
|
||||||
static QString shadowedName(const QString &name, int seen);
|
static QString shadowedName(const QString &name, int seen);
|
||||||
@@ -119,7 +121,7 @@ public:
|
|||||||
QByteArray type; // Type for further processing
|
QByteArray type; // Type for further processing
|
||||||
QString displayedType;// Displayed type (optional)
|
QString displayedType;// Displayed type (optional)
|
||||||
QByteArray variable; // Name of internal Gdb variable if created
|
QByteArray variable; // Name of internal Gdb variable if created
|
||||||
QByteArray addr; // Displayed address
|
quint64 address; // Displayed address
|
||||||
QString framekey; // Key for type cache
|
QString framekey; // Key for type cache
|
||||||
QScriptValue scriptValue; // If needed...
|
QScriptValue scriptValue; // If needed...
|
||||||
bool hasChildren;
|
bool hasChildren;
|
||||||
@@ -127,6 +129,7 @@ public:
|
|||||||
bool valueEnabled; // Value will be greyed out or not
|
bool valueEnabled; // Value will be greyed out or not
|
||||||
bool valueEditable; // Value will be editable
|
bool valueEditable; // Value will be editable
|
||||||
bool error;
|
bool error;
|
||||||
|
QByteArray dumperFlags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int source; // Originated from dumper or symbol evaluation? (CDB only)
|
int source; // Originated from dumper or symbol evaluation? (CDB only)
|
||||||
|
|||||||
@@ -668,16 +668,14 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
|
|||||||
case LocalsExpressionRole: {
|
case LocalsExpressionRole: {
|
||||||
if (!data.exp.isEmpty())
|
if (!data.exp.isEmpty())
|
||||||
return data.exp;
|
return data.exp;
|
||||||
if (!data.addr.isEmpty() && !data.type.isEmpty()) {
|
if (data.address && !data.type.isEmpty()) {
|
||||||
bool ok;
|
return QString::fromAscii("*(%1*)%2").
|
||||||
const quint64 addr = data.addr.toULongLong(&ok, 16);
|
arg(QLatin1String(data.type), QLatin1String(data.hexAddress()));
|
||||||
if (ok && addr)
|
|
||||||
return QString("*(%1*)%2").arg(QLatin1String(data.type)).arg(addr);
|
|
||||||
}
|
}
|
||||||
WatchItem *parent = item->parent;
|
WatchItem *parent = item->parent;
|
||||||
if (parent && !parent->exp.isEmpty())
|
if (parent && !parent->exp.isEmpty())
|
||||||
return QString("(%1).%2")
|
return QString::fromAscii("(%1).%2")
|
||||||
.arg(QString::fromLatin1(parent->exp)).arg(data.name);
|
.arg(QString::fromLatin1(parent->exp), data.name);
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1314,7 +1312,7 @@ static void swapEndian(char *d, int nchar)
|
|||||||
|
|
||||||
void WatchHandler::showEditValue(const WatchData &data)
|
void WatchHandler::showEditValue(const WatchData &data)
|
||||||
{
|
{
|
||||||
const QByteArray key = data.addr.isEmpty() ? data.iname : data.addr;
|
const QByteArray key = data.address ? data.hexAddress() : data.iname;
|
||||||
QObject *w = m_editHandlers.value(key);
|
QObject *w = m_editHandlers.value(key);
|
||||||
if (data.editformat == 0x0) {
|
if (data.editformat == 0x0) {
|
||||||
m_editHandlers.remove(data.iname);
|
m_editHandlers.remove(data.iname);
|
||||||
@@ -1325,10 +1323,10 @@ void WatchHandler::showEditValue(const WatchData &data)
|
|||||||
if (!l) {
|
if (!l) {
|
||||||
delete w;
|
delete w;
|
||||||
l = new QLabel;
|
l = new QLabel;
|
||||||
QString addr = tr("unknown address");
|
const QString title = data.address ?
|
||||||
if (!data.addr.isEmpty())
|
tr("%1 Object at %2").arg(QLatin1String(data.type), QLatin1String(data.hexAddress())) :
|
||||||
addr = QString::fromLatin1(data.addr);
|
tr("%1 Object at Unknown Address").arg(QLatin1String(data.type));
|
||||||
l->setWindowTitle(tr("%1 object at %2").arg(data.type, addr));
|
l->setWindowTitle(title);
|
||||||
m_editHandlers[key] = l;
|
m_editHandlers[key] = l;
|
||||||
}
|
}
|
||||||
int width, height, format;
|
int width, height, format;
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ namespace Internal {
|
|||||||
|
|
||||||
class WatchItem;
|
class WatchItem;
|
||||||
class WatchHandler;
|
class WatchHandler;
|
||||||
class WatchData;
|
|
||||||
|
|
||||||
enum WatchType
|
enum WatchType
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1201,7 +1201,11 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
// in rare cases we need more or less:
|
// in rare cases we need more or less:
|
||||||
switch (td.type) {
|
switch (td.type) {
|
||||||
case QAbstractItemType:
|
case QAbstractItemType:
|
||||||
inner = data.addr.mid(1);
|
if (data.dumperFlags.isEmpty()) {
|
||||||
|
qWarning("Internal error: empty dumper state '%s'.", data.iname.constData());
|
||||||
|
} else {
|
||||||
|
inner = data.dumperFlags.mid(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case QObjectSlotType:
|
case QObjectSlotType:
|
||||||
case QObjectSignalType: {
|
case QObjectSignalType: {
|
||||||
@@ -1226,12 +1230,12 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
//qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
|
//qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
|
||||||
// << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
|
// << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
|
||||||
extraArgs[2] = evaluationSizeofTypeExpression(nodetype, debugger);
|
extraArgs[2] = evaluationSizeofTypeExpression(nodetype, debugger);
|
||||||
extraArgs[3] = qMapNodeValueOffsetExpression(nodetype, data.addr, debugger);
|
extraArgs[3] = qMapNodeValueOffsetExpression(nodetype, data.hexAddress(), debugger);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QMapNodeType:
|
case QMapNodeType:
|
||||||
extraArgs[2] = evaluationSizeofTypeExpression(data.type, debugger);
|
extraArgs[2] = evaluationSizeofTypeExpression(data.type, debugger);
|
||||||
extraArgs[3] = qMapNodeValueOffsetExpression(data.type, data.addr, debugger);
|
extraArgs[3] = qMapNodeValueOffsetExpression(data.type, data.hexAddress(), debugger);
|
||||||
break;
|
break;
|
||||||
case StdVectorType:
|
case StdVectorType:
|
||||||
//qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
|
//qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
|
||||||
@@ -1280,7 +1284,9 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
|||||||
// occasionally fails for complex types (std::string).
|
// occasionally fails for complex types (std::string).
|
||||||
// We need an address as CDB cannot do the 0-trick.
|
// We need an address as CDB cannot do the 0-trick.
|
||||||
// Use data address or try at least cache if missing.
|
// Use data address or try at least cache if missing.
|
||||||
const QByteArray address = data.addr.isEmpty() ? "DUMMY_ADDRESS" : data.addr;
|
const QByteArray address = data.address ?
|
||||||
|
data.hexAddress() :
|
||||||
|
"DUMMY_ADDRESS";
|
||||||
QByteArray offsetExpr = "(size_t)&(((" + pairType + " *)" + address
|
QByteArray offsetExpr = "(size_t)&(((" + pairType + " *)" + address
|
||||||
+ ")->second)" + '-' + address;
|
+ ")->second)" + '-' + address;
|
||||||
extraArgs[2] = lookupCdbDummyAddressExpression(offsetExpr, address);
|
extraArgs[2] = lookupCdbDummyAddressExpression(offsetExpr, address);
|
||||||
@@ -1495,7 +1501,13 @@ static void gbdMiToWatchData(const GdbMi &root,
|
|||||||
w.editvalue = b;
|
w.editvalue = b;
|
||||||
if (gdbMiGetByteArrayValue(&b, root, "exp"))
|
if (gdbMiGetByteArrayValue(&b, root, "exp"))
|
||||||
w.exp = b;
|
w.exp = b;
|
||||||
gdbMiGetByteArrayValue(&w.addr, root, "addr");
|
QByteArray addressBA;
|
||||||
|
gdbMiGetByteArrayValue(&addressBA, root, "addr");
|
||||||
|
if (addressBA.startsWith("0x")) { // Item model dumper pulls tricks
|
||||||
|
w.setHexAddress(addressBA);
|
||||||
|
} else {
|
||||||
|
w.dumperFlags = addressBA;
|
||||||
|
}
|
||||||
gdbMiGetBoolValue(&w.valueEnabled, root, "valueenabled");
|
gdbMiGetBoolValue(&w.valueEnabled, root, "valueenabled");
|
||||||
gdbMiGetBoolValue(&w.valueEditable, root, "valueeditable");
|
gdbMiGetBoolValue(&w.valueEditable, root, "valueeditable");
|
||||||
if (gdbMiGetStringValue(&v, root, "valuetooltip", "valuetooltipencoded"))
|
if (gdbMiGetStringValue(&v, root, "valuetooltip", "valuetooltipencoded"))
|
||||||
@@ -1622,9 +1634,13 @@ void setWatchDataAddress(WatchData &data, const GdbMi &mi)
|
|||||||
|
|
||||||
void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr)
|
void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr)
|
||||||
{
|
{
|
||||||
data.addr = addr;
|
if (addr.startsWith("0x")) { // Item model dumpers pull tricks
|
||||||
if (data.exp.isEmpty() && !data.addr.startsWith("$"))
|
data.setHexAddress(addr);
|
||||||
data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" + data.addr;
|
} else {
|
||||||
|
data.dumperFlags = addr;
|
||||||
|
}
|
||||||
|
if (data.exp.isEmpty() && !data.dumperFlags.startsWith('$'))
|
||||||
|
data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" +data.hexAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the "type" and "displayedtype" children of root and set up type.
|
// Find the "type" and "displayedtype" children of root and set up type.
|
||||||
|
|||||||
Reference in New Issue
Block a user