forked from qt-creator/qt-creator
Cdb: Introduce SymbolGroupChildInfo
Holds the offset and type of a symbol ancestor. This information is cached and used to collect data directly via offset instead of expanding known symbols. Change-Id: I0c08f6911dfbb6016c4bb12cb6325be873c6000a Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -40,9 +40,14 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <ctype.h>
|
||||
#include <unordered_map>
|
||||
|
||||
typedef std::vector<int>::size_type VectorIndexType;
|
||||
|
||||
typedef std::unordered_map<std::string, SymbolAncestorInfo> AncestorInfos;
|
||||
|
||||
static std::unordered_map<std::string, AncestorInfos> typeAncestorInfos;
|
||||
|
||||
/*!
|
||||
\class SymbolGroupValueContext
|
||||
\brief The SymbolGroupValueContext class passes all IDebug interfaces
|
||||
@@ -129,6 +134,93 @@ SymbolGroupValue SymbolGroupValue::operator[](unsigned index) const
|
||||
return SymbolGroupValue(m_errorMessage);
|
||||
}
|
||||
|
||||
SymbolGroupValue SymbolGroupValue::addSymbolForAncestor(const std::string &ancestorName) const
|
||||
{
|
||||
const SymbolAncestorInfo info = infoOfAncestor(ancestorName);
|
||||
if (info.isValid()) {
|
||||
const ULONG64 base = isPointerType(type()) ? pointerValue() : address();
|
||||
const std::string &pointerToType =
|
||||
pointedToSymbolName(base + info.offset, stripClassPrefixes(info.type));
|
||||
if (SymbolGroupNode *ancestorNode =
|
||||
node()->symbolGroup()->addSymbol(module(), pointerToType, "", "", &std::string())) {
|
||||
return SymbolGroupValue(ancestorNode, m_context);
|
||||
}
|
||||
}
|
||||
if (isValid() && SymbolGroupValue::verbose) { // Do not report subsequent errors
|
||||
DebugPrint dp;
|
||||
dp << this->name() << "::addSymbolForAncestor(\"" << ancestorName << "\") failed. ";
|
||||
formatNodeError(m_node, dp);
|
||||
}
|
||||
return SymbolGroupValue(m_errorMessage);
|
||||
}
|
||||
|
||||
int SymbolGroupValue::readIntegerFromAncestor(const std::string &name, int defaultValue) const
|
||||
{
|
||||
return readPODFromAncestor<int>(name, defaultValue);
|
||||
}
|
||||
|
||||
LONG64 SymbolGroupValue::offsetOfAncestor(const std::string &name) const
|
||||
{
|
||||
return infoOfAncestor(name).offset;
|
||||
}
|
||||
|
||||
ULONG64 SymbolGroupValue::addressOfAncestor(const std::string &name) const
|
||||
{
|
||||
const ULONG64 base = isPointerType(type()) ? pointerValue() : address();
|
||||
LONG64 offset = offsetOfAncestor(name);
|
||||
return offset >= 0 ? base + ULONG64(offset) : 0;
|
||||
}
|
||||
|
||||
std::string SymbolGroupValue::typeOfAncestor(const std::string &name) const
|
||||
{
|
||||
return infoOfAncestor(name).type;
|
||||
}
|
||||
|
||||
SymbolAncestorInfo SymbolGroupValue::infoOfAncestor(const std::string &name) const
|
||||
{
|
||||
const std::string &typeName = type();
|
||||
AncestorInfos &offsets = typeAncestorInfos[typeName];
|
||||
auto offsetIt = offsets.find(name);
|
||||
if (offsetIt != offsets.end())
|
||||
return offsetIt->second;
|
||||
|
||||
SymbolAncestorInfo info;
|
||||
if (!ensureExpanded())
|
||||
return info;
|
||||
|
||||
if (AbstractSymbolGroupNode *abstractChildNode = m_node->childByIName(name.c_str())) {
|
||||
if (SymbolGroupNode *childNode = abstractChildNode->asSymbolGroupNode()) {
|
||||
SymbolGroupValue child(childNode, m_context);
|
||||
ULONG64 childAddress = child.address();
|
||||
if (childAddress == 0)
|
||||
return info;
|
||||
const ULONG64 base = isPointerType(typeName) ? pointerValue() : address();
|
||||
info.offset = LONG64(childAddress - base);
|
||||
info.type = child.type();
|
||||
}
|
||||
}
|
||||
|
||||
if (!info.isValid()) {
|
||||
// Search recursively for ancestor
|
||||
for (AbstractSymbolGroupNode *abstractChildNode : m_node->children()) {
|
||||
if (SymbolGroupNode *childNode = abstractChildNode->asSymbolGroupNode()) {
|
||||
SymbolGroupValue child(childNode, m_context);
|
||||
if (isPointerType(child.type()))
|
||||
continue;
|
||||
info = child.infoOfAncestor(name);
|
||||
if (info.isValid()) {
|
||||
info.offset += offsetOfAncestor(child.name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info.isValid())
|
||||
offsets[name] = info;
|
||||
return info;
|
||||
}
|
||||
|
||||
unsigned SymbolGroupValue::childCount() const
|
||||
{
|
||||
if (ensureExpanded())
|
||||
@@ -254,12 +346,29 @@ template<class POD>
|
||||
return rc;
|
||||
}
|
||||
|
||||
template<class POD>
|
||||
POD SymbolGroupValue::readPODFromAncestor(const std::string &name, POD defaultValue) const
|
||||
{
|
||||
ULONG64 address = addressOfAncestor(name.c_str());
|
||||
if (address == 0)
|
||||
return defaultValue;
|
||||
return readPODFromMemory<POD>(m_context.dataspaces, address, sizeof(POD), defaultValue, 0);
|
||||
}
|
||||
|
||||
ULONG64 SymbolGroupValue::readPointerValue(CIDebugDataSpaces *ds, ULONG64 address,
|
||||
std::string *errorMessage /* = 0 */)
|
||||
{
|
||||
return readPODFromMemory<ULONG64>(ds, address, SymbolGroupValue::pointerSize(), 0, errorMessage);
|
||||
}
|
||||
|
||||
ULONG64 SymbolGroupValue::readPointerValueFromAncestor(const std::string &name) const
|
||||
{
|
||||
ULONG64 address = addressOfAncestor(name.c_str());
|
||||
if (address == 0)
|
||||
return 0;
|
||||
return readPointerValue(m_context.dataspaces, address);
|
||||
}
|
||||
|
||||
ULONG64 SymbolGroupValue::readUnsignedValue(CIDebugDataSpaces *ds,
|
||||
ULONG64 address, ULONG debuggeeTypeSize,
|
||||
ULONG64 defaultValue,
|
||||
|
||||
Reference in New Issue
Block a user