diff options
author | David Schulz <david.schulz@qt.io> | 2016-08-30 13:46:23 +0200 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2016-09-15 07:27:27 +0000 |
commit | 6b112c1b04d3fbed65492a2a05e2c34f71c6bc8d (patch) | |
tree | 60837108d5cccc08e399ec5f767345e9e900c1ea | |
parent | 21dc290360f80b007d36545f18b316f8236d659e (diff) |
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>
-rw-r--r-- | src/libs/qtcreatorcdbext/symbolgroupvalue.cpp | 109 | ||||
-rw-r--r-- | src/libs/qtcreatorcdbext/symbolgroupvalue.h | 17 |
2 files changed, 126 insertions, 0 deletions
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp index 131685b103..5d7147f373 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp @@ -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, diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.h b/src/libs/qtcreatorcdbext/symbolgroupvalue.h index 87e6c9a109..d14ee0e3dd 100644 --- a/src/libs/qtcreatorcdbext/symbolgroupvalue.h +++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.h @@ -46,6 +46,13 @@ struct SymbolGroupValueContext CIDebugSymbols *symbols = nullptr; }; +struct SymbolAncestorInfo +{ + bool isValid() const { return offset >= 0 && !type.empty(); } + std::string type; + LONG64 offset = -1; +}; + class SymbolGroupValue { explicit SymbolGroupValue(const std::string &parentError); @@ -80,6 +87,15 @@ public: std::wstring value() const; unsigned size() const; + //offset based access to ancestors + SymbolGroupValue addSymbolForAncestor(const std::string &ancestorName) const; + ULONG64 readPointerValueFromAncestor(const std::string &name) const; + int readIntegerFromAncestor(const std::string &name, int defaultValue = -1) const; + LONG64 offsetOfAncestor(const std::string &name) const; + ULONG64 addressOfAncestor(const std::string &name) const; + std::string typeOfAncestor(const std::string &childName) const; + SymbolAncestorInfo infoOfAncestor(const std::string &name) const; + SymbolGroupNode *node() const { return m_node; } SymbolGroupValueContext context() const { return m_context; } @@ -170,6 +186,7 @@ public: private: bool ensureExpanded() const; SymbolGroupValue typeCastedValue(ULONG64 address, const char *type) const; + template<class POD> POD readPODFromAncestor(const std::string &name, POD defaultValue) const; SymbolGroupNode *m_node = 0; SymbolGroupValueContext m_context; |