Debugger: Have Python dumper print type size information.

For memory views. In the dumper, create a cache of TypeInfo
structs to contain type information and print the new entries
in each call of bb().

Collect the information in the gdb engine.
Replace WatchData::origAddress by WatchData::ReferencingAddress
to be able to correctly handle automatically dereferenced
pointers of the gdb engine. Whereas 'address' of a automatically
dereferenced used to be that of the pointer, it is now that
of the dereferenced item matching the size reported, enabling
memory views. Referencing address is now the address of the pointer.

Reviewed-by: hjk
This commit is contained in:
Friedemann Kleint
2011-04-12 15:56:03 +02:00
parent fc2e7263d5
commit 67d391019b
9 changed files with 79 additions and 33 deletions

View File

@@ -103,6 +103,13 @@ def hasInferiorThreadList():
typeCache = {} typeCache = {}
class TypeInfo:
def __init__(self, type):
self.size = type.sizeof
self.reported = False
typeInfoCache = {}
def lookupType(typestring): def lookupType(typestring):
type = typeCache.get(typestring) type = typeCache.get(typestring)
#warn("LOOKUP 1: %s -> %s" % (typestring, type)) #warn("LOOKUP 1: %s -> %s" % (typestring, type))
@@ -331,8 +338,13 @@ class SubItem:
#warn("TYPE VALUE: %s" % self.d.currentValue) #warn("TYPE VALUE: %s" % self.d.currentValue)
type = stripClassTag(str(self.d.currentType)) type = stripClassTag(str(self.d.currentType))
#warn("TYPE: '%s' DEFAULT: '%s'" % (type, self.d.currentChildType)) #warn("TYPE: '%s' DEFAULT: '%s'" % (type, self.d.currentChildType))
if len(type) > 0 and type != self.d.currentChildType: if len(type) > 0 and type != self.d.currentChildType:
self.d.put('type="%s",' % type) # str(type.unqualified()) ? self.d.put('type="%s",' % type) # str(type.unqualified()) ?
if not type in typeInfoCache:
typeObj = lookupType(type)
if not typeObj is None:
typeInfoCache[type] = TypeInfo(typeObj)
if not self.d.currentValueEncoding is None: if not self.d.currentValueEncoding is None:
self.d.put('valueencoded="%d",' % self.d.currentValueEncoding) self.d.put('valueencoded="%d",' % self.d.currentValueEncoding)
if not self.d.currentValue is None: if not self.d.currentValue is None:
@@ -1082,7 +1094,14 @@ class FrameCommand(gdb.Command):
FrameCommand() FrameCommand()
def bb(args): def bb(args):
return 'data=[' + Dumper(args).output + ']' output = 'data=[' + Dumper(args).output + '],typeinfo=['
for typeName, typeInfo in typeInfoCache.iteritems():
if not typeInfo.reported:
output += '{name="' + base64.b64encode(typeName)
output += '",size="' + str(typeInfo.size) + '"},'
typeInfo.reported = True
output += ']';
return output
####################################################################### #######################################################################

View File

@@ -1367,7 +1367,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
data.variable = name; data.variable = name;
setWatchDataType(data, item.findChild("type")); setWatchDataType(data, item.findChild("type"));
setWatchDataValue(data, item); setWatchDataValue(data, item);
setWatchDataAddress(data, item.findChild("addr")); setWatchDataAddress(data, item.findChild("addr"), GdbMi());
data.setHasChildren(false); data.setHasChildren(false);
insertData(data); insertData(data);
} else if (parent.iname.endsWith('.')) { } else if (parent.iname.endsWith('.')) {
@@ -1391,7 +1391,7 @@ void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item,
data.sortId = sortId; data.sortId = sortId;
setWatchDataType(data, item.findChild("type")); setWatchDataType(data, item.findChild("type"));
setWatchDataValue(data, item); setWatchDataValue(data, item);
setWatchDataAddress(data, item.findChild("addr")); setWatchDataAddress(data, item.findChild("addr"), GdbMi());
setWatchDataChildCount(data, item.findChild("numchild")); setWatchDataChildCount(data, item.findChild("numchild"));
if (!watchHandler()->isExpandedIName(data.iname)) if (!watchHandler()->isExpandedIName(data.iname))
data.setChildrenUnneeded(); data.setChildrenUnneeded();

View File

@@ -660,6 +660,14 @@ private: ////////// View & Data Stuff //////////
void handleStackListArgumentsClassic(const GdbResponse &response); void handleStackListArgumentsClassic(const GdbResponse &response);
QSet<QByteArray> m_processedNames; QSet<QByteArray> m_processedNames;
struct TypeInfo
{
TypeInfo(uint s = 0) : size(s) {}
uint size;
};
QHash<QByteArray, TypeInfo> m_typeInfoCache;
// //
// Dumper Management // Dumper Management

View File

@@ -158,6 +158,22 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
} }
parseWatchData(watchHandler()->expandedINames(), dummy, child, &list); parseWatchData(watchHandler()->expandedINames(), dummy, child, &list);
} }
const GdbMi typeInfo = all.findChild("typeinfo");
if (typeInfo.type() == GdbMi::List) {
foreach (const GdbMi &s, typeInfo.children()) {
const GdbMi name = s.findChild("name");
const GdbMi size = s.findChild("size");
if (name.isValid() && size.isValid())
m_typeInfoCache.insert(QByteArray::fromBase64(name.data()),
TypeInfo(size.data().toUInt()));
}
}
for (int i = 0; i != list.size(); ++i) {
const TypeInfo ti = m_typeInfoCache.value(list.at(i).type);
if (ti.size)
list[i].size = ti.size;
}
watchHandler()->insertBulkData(list); watchHandler()->insertBulkData(list);
//PENDING_DEBUG("AFTER handleStackFrame()"); //PENDING_DEBUG("AFTER handleStackFrame()");

View File

@@ -125,7 +125,7 @@ WatchData::WatchData() :
state(InitialState), state(InitialState),
editformat(0), editformat(0),
address(0), address(0),
origAddress(0), referencingAddress(0),
size(0), size(0),
bitpos(0), bitpos(0),
bitsize(0), bitsize(0),
@@ -305,9 +305,9 @@ QString WatchData::toString() const
str << "addr=\"0x" << address << doubleQuoteComma; str << "addr=\"0x" << address << doubleQuoteComma;
str.setIntegerBase(10); str.setIntegerBase(10);
} }
if (origAddress) { if (referencingAddress) {
str.setIntegerBase(16); str.setIntegerBase(16);
str << "origaddr=\"0x" << origAddress << doubleQuoteComma; str << "referencingaddr=\"0x" << referencingAddress << doubleQuoteComma;
str.setIntegerBase(10); str.setIntegerBase(10);
} }
if (!exp.isEmpty()) if (!exp.isEmpty())
@@ -373,9 +373,9 @@ QString WatchData::toToolTip() const
formatToolTipRow(str, tr("Value"), val); formatToolTipRow(str, tr("Value"), val);
formatToolTipRow(str, tr("Object Address"), formatToolTipRow(str, tr("Object Address"),
QString::fromAscii(hexAddress())); QString::fromAscii(hexAddress()));
if (origAddress) if (referencingAddress)
formatToolTipRow(str, tr("Original Address"), formatToolTipRow(str, tr("Referencing Address"),
QString::fromAscii(hexOrigAddress())); QString::fromAscii(hexReferencingAddress()));
if (size) if (size)
formatToolTipRow(str, tr("Size"), formatToolTipRow(str, tr("Size"),
QString::number(size)); QString::number(size));
@@ -419,9 +419,9 @@ QByteArray WatchData::hexAddress() const
return address ? (QByteArray("0x") + QByteArray::number(address, 16)) : QByteArray(); return address ? (QByteArray("0x") + QByteArray::number(address, 16)) : QByteArray();
} }
QByteArray WatchData::hexOrigAddress() const QByteArray WatchData::hexReferencingAddress() const
{ {
return origAddress ? (QByteArray("0x") + QByteArray::number(origAddress, 16)) : QByteArray(); return referencingAddress ? (QByteArray("0x") + QByteArray::number(referencingAddress, 16)) : QByteArray();
} }
} // namespace Internal } // namespace Internal

View File

@@ -113,7 +113,7 @@ public:
quint64 coreAddress() const; quint64 coreAddress() const;
QByteArray hexAddress() const; QByteArray hexAddress() const;
QByteArray hexOrigAddress() const; QByteArray hexReferencingAddress() const;
public: public:
quint64 id; // Token for the engine for internal mapping quint64 id; // Token for the engine for internal mapping
@@ -129,7 +129,7 @@ public:
QByteArray type; // Type for further processing QByteArray type; // Type for further processing
QString displayedType;// Displayed type (optional) QString displayedType;// Displayed type (optional)
quint64 address; // Displayed address quint64 address; // Displayed address
quint64 origAddress; // Original address for dereferenced pointers quint64 referencingAddress; // Address of the pointer referencing this item (gdb auto-deref)
uint size; // Size uint size; // Size
uint bitpos; // Position within bit fields uint bitpos; // Position within bit fields
uint bitsize; // Size in case of bit fields uint bitsize; // Size in case of bit fields

View File

@@ -641,9 +641,9 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case 1: case 1:
result = removeInitialNamespace(truncateValue( result = removeInitialNamespace(truncateValue(
formattedValue(data, itemFormat(data))), ns); formattedValue(data, itemFormat(data))), ns);
if (data.origAddress) { if (data.referencingAddress) {
result += QLatin1String(" @"); result += QLatin1String(" @");
result += QString::fromLatin1(data.hexOrigAddress()); result += QString::fromLatin1(data.hexAddress());
} }
break; break;
case 2: case 2:
@@ -696,7 +696,7 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
return m_handler->m_expandedINames.contains(data.iname); return m_handler->m_expandedINames.contains(data.iname);
case LocalsTypeFormatListRole: { case LocalsTypeFormatListRole: {
if (data.origAddress || data.type.endsWith('*')) if (data.referencingAddress || data.type.endsWith('*'))
return QStringList() return QStringList()
<< tr("Raw pointer") << tr("Raw pointer")
<< tr("Latin1 string") << tr("Latin1 string")

View File

@@ -732,26 +732,31 @@ static void setWatchDataExpression(WatchData &data, const GdbMi &mi)
data.exp = mi.data(); data.exp = mi.data();
} }
static void setWatchDataAddressHelper(WatchData &data, const QByteArray &addr) static void setWatchDataAddress(WatchData &data, quint64 address , quint64 origAddress = 0)
{ {
if (addr.startsWith("0x")) { // Item model dumpers pull tricks if (origAddress) { // Gdb dumpers reports the dereferenced address as origAddress
data.setHexAddress(addr); data.address = origAddress;
data.referencingAddress = address;
} else { } else {
data.dumperFlags = addr; data.address = address;
} }
if (data.exp.isEmpty() && !data.dumperFlags.startsWith('$')) if (data.exp.isEmpty() && !data.dumperFlags.startsWith('$'))
data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" +data.hexAddress(); data.exp = "*(" + gdbQuoteTypes(data.type) + "*)" +data.hexAddress();
} }
void setWatchDataAddress(WatchData &data, const GdbMi &mi) void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &origAddressMi)
{ {
if (mi.isValid()) if (!addressMi.isValid())
setWatchDataAddressHelper(data, mi.data()); return;
} const QByteArray addressBA = addressMi.data();
if (!addressBA.startsWith("0x")) { // Item model dumpers pull tricks.
static void setWatchDataOrigAddress(WatchData &data, const GdbMi &mi) data.dumperFlags = addressBA;
{ return;
data.origAddress = mi.data().toULongLong(0, 16); }
const quint64 address = addressBA.toULongLong(0, 16);
const quint64 origAddress = origAddressMi.isValid() ?
origAddressMi.data().toULongLong(0, 16) : quint64(0);
setWatchDataAddress(data, address, origAddress);
} }
static void setWatchDataSize(WatchData &data, const GdbMi &mi) static void setWatchDataSize(WatchData &data, const GdbMi &mi)
@@ -811,8 +816,7 @@ void parseWatchData(const QSet<QByteArray> &expandedINames,
data.bitsize = mi.data().toInt(); data.bitsize = mi.data().toInt();
setWatchDataValue(data, item); setWatchDataValue(data, item);
setWatchDataAddress(data, item.findChild("addr")); setWatchDataAddress(data, item.findChild("addr"), item.findChild("origaddr"));
setWatchDataOrigAddress(data, item.findChild("origaddr"));
setWatchDataSize(data, item.findChild("size")); setWatchDataSize(data, item.findChild("size"));
setWatchDataExpression(data, item.findChild("exp")); setWatchDataExpression(data, item.findChild("exp"));
setWatchDataValueEnabled(data, item.findChild("valueenabled")); setWatchDataValueEnabled(data, item.findChild("valueenabled"));
@@ -851,8 +855,7 @@ void parseWatchData(const QSet<QByteArray> &expandedINames,
if (!data1.name.isEmpty() && data1.name.at(0).isDigit()) if (!data1.name.isEmpty() && data1.name.at(0).isDigit())
data1.name = _c('[') + data1.name + _c(']'); data1.name = _c('[') + data1.name + _c(']');
if (addressStep) { if (addressStep) {
const QByteArray addr = "0x" + QByteArray::number(addressBase, 16); setWatchDataAddress(data1, addressBase);
setWatchDataAddressHelper(data1, addr);
addressBase += addressStep; addressBase += addressStep;
} }
QByteArray key = child.findChild("key").data(); QByteArray key = child.findChild("key").data();

View File

@@ -119,7 +119,7 @@ void setWatchDataValueToolTip(WatchData &data, const GdbMi &mi,
int encoding); int encoding);
void setWatchDataChildCount(WatchData &data, const GdbMi &mi); void setWatchDataChildCount(WatchData &data, const GdbMi &mi);
void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi); void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi);
void setWatchDataAddress(WatchData &data, const GdbMi &mi); void setWatchDataAddress(WatchData &data, const GdbMi &addressMi, const GdbMi &origAddressMi);
void setWatchDataType(WatchData &data, const GdbMi &mi); void setWatchDataType(WatchData &data, const GdbMi &mi);
void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi); void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);