forked from qt-creator/qt-creator
CDB: Fix STL debugger helpers for MSVC2012 beta.
In MSVC2012, more bases classes for std::string and containers were introduced whereas std::pair_base was removed compared to MSVC2010. Add a findMember() function to be able to skip base classes when looking for a certain member to finally fix this issue. Introduce SymbolGroupValue::parent()/childCount() and simplify the helpers using it. Change-Id: I7a6aad5c07739ca9cbf350489acd6d03bd1865e8 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -98,8 +98,9 @@ static inline std::string fixInnerType(std::string type,
|
|||||||
// Return size from an STL vector (last/first iterators).
|
// Return size from an STL vector (last/first iterators).
|
||||||
static inline int msvcStdVectorSize(const SymbolGroupValue &v)
|
static inline int msvcStdVectorSize(const SymbolGroupValue &v)
|
||||||
{
|
{
|
||||||
if (const SymbolGroupValue myFirstPtrV = v["_Myfirst"]) {
|
// MSVC2012 has 2 base classes, MSVC2010 1, MSVC2008 none
|
||||||
if (const SymbolGroupValue myLastPtrV = v["_Mylast"]) {
|
if (const SymbolGroupValue myFirstPtrV = SymbolGroupValue::findMember(v, "_Myfirst")) {
|
||||||
|
if (const SymbolGroupValue myLastPtrV = myFirstPtrV.parent()["_Mylast"]) {
|
||||||
const ULONG64 firstPtr = myFirstPtrV.pointerValue();
|
const ULONG64 firstPtr = myFirstPtrV.pointerValue();
|
||||||
const ULONG64 lastPtr = myLastPtrV.pointerValue();
|
const ULONG64 lastPtr = myLastPtrV.pointerValue();
|
||||||
if (!firstPtr || lastPtr < firstPtr)
|
if (!firstPtr || lastPtr < firstPtr)
|
||||||
@@ -182,46 +183,20 @@ int containerSize(KnownType kt, const SymbolGroupValue &v)
|
|||||||
if (const SymbolGroupValue base = v[unsigned(0)])
|
if (const SymbolGroupValue base = v[unsigned(0)])
|
||||||
return containerSize(KT_QMap, base);
|
return containerSize(KT_QMap, base);
|
||||||
break;
|
break;
|
||||||
case KT_StdVector: {
|
case KT_StdVector:
|
||||||
if (const SymbolGroupValue base = v[unsigned(0)]) {
|
return msvcStdVectorSize(v);
|
||||||
const int msvc10Size = msvcStdVectorSize(base);
|
case KT_StdDeque: // MSVC2012 has many base classes, MSVC2010 1, MSVC2008 none
|
||||||
if (msvc10Size >= 0)
|
case KT_StdSet:
|
||||||
return msvc10Size;
|
case KT_StdMap:
|
||||||
}
|
case KT_StdMultiMap:
|
||||||
const int msvc8Size = msvcStdVectorSize(v);
|
|
||||||
if (msvc8Size >= 0)
|
|
||||||
return msvc8Size;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KT_StdList:
|
case KT_StdList:
|
||||||
if (const SymbolGroupValue sizeV = v["_Mysize"]) // VS 8
|
if (const SymbolGroupValue size = SymbolGroupValue::findMember(v, "_Mysize"))
|
||||||
return sizeV.intValue();
|
return size.intValue();
|
||||||
if (const SymbolGroupValue sizeV = v[unsigned(0)][unsigned(0)]["_Mysize"]) // VS10
|
|
||||||
return sizeV.intValue();
|
|
||||||
break;
|
|
||||||
case KT_StdDeque: {
|
|
||||||
const SymbolGroupValue msvc10sizeV = v[unsigned(0)]["_Mysize"]; // VS10
|
|
||||||
if (msvc10sizeV)
|
|
||||||
return msvc10sizeV.intValue();
|
|
||||||
const SymbolGroupValue msvc8sizeV = v["_Mysize"]; // VS8
|
|
||||||
if (msvc8sizeV)
|
|
||||||
return msvc8sizeV.intValue();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case KT_StdStack:
|
case KT_StdStack:
|
||||||
if (const SymbolGroupValue deque = v[unsigned(0)])
|
if (const SymbolGroupValue deque = v[unsigned(0)])
|
||||||
return containerSize(KT_StdDeque, deque);
|
return containerSize(KT_StdDeque, deque);
|
||||||
break;
|
break;
|
||||||
case KT_StdSet:
|
|
||||||
case KT_StdMap:
|
|
||||||
case KT_StdMultiMap:
|
|
||||||
if (const SymbolGroupValue baseV = v[unsigned(0)]) {
|
|
||||||
if (const SymbolGroupValue sizeV = baseV["_Mysize"]) // VS 8
|
|
||||||
return sizeV.intValue();
|
|
||||||
if (const SymbolGroupValue sizeV = baseV[unsigned(0)][unsigned(0)]["_Mysize"]) // VS 10
|
|
||||||
return sizeV.intValue();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -258,20 +233,19 @@ private:
|
|||||||
const char *m_name;
|
const char *m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::list<T>: Dummy head node and then a linked list of "_Next", "_Myval".
|
// std::list<T>: Skip dummy head node and then a linked list of "_Next", "_Myval".
|
||||||
static inline AbstractSymbolGroupNodePtrVector stdListChildList(SymbolGroupNode *n, int count,
|
static inline AbstractSymbolGroupNodePtrVector stdListChildList(SymbolGroupNode *n, int count,
|
||||||
const SymbolGroupValueContext &ctx)
|
const SymbolGroupValueContext &ctx)
|
||||||
{
|
{
|
||||||
if (!count)
|
if (!count)
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
const SymbolGroupValue head = SymbolGroupValue(n, ctx)[unsigned(0)][unsigned(0)]["_Myhead"]["_Next"];
|
const SymbolGroupValue head = SymbolGroupValue::findMember(SymbolGroupValue(n, ctx), "_Myhead")["_Next"];
|
||||||
if (!head) {
|
if (head)
|
||||||
|
return linkedListChildList(head, count, MemberByName("_Myval"), MemberByName("_Next"));
|
||||||
if (SymbolGroupValue::verbose)
|
if (SymbolGroupValue::verbose)
|
||||||
DebugPrint() << "std::list failure: " << head;
|
DebugPrint() << "std::list failure: " << head;
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
}
|
}
|
||||||
return linkedListChildList(head, count, MemberByName("_Myval"), MemberByName("_Next"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// QLinkedList<T>: Dummy head node and then a linked list of "n", "t".
|
// QLinkedList<T>: Dummy head node and then a linked list of "n", "t".
|
||||||
static inline AbstractSymbolGroupNodePtrVector qLinkedListChildList(SymbolGroupNode *n, int count,
|
static inline AbstractSymbolGroupNodePtrVector qLinkedListChildList(SymbolGroupNode *n, int count,
|
||||||
@@ -346,25 +320,24 @@ static inline AbstractSymbolGroupNodePtrVector
|
|||||||
static inline AbstractSymbolGroupNodePtrVector
|
static inline AbstractSymbolGroupNodePtrVector
|
||||||
stdVectorChildList(SymbolGroupNode *n, int count, const SymbolGroupValueContext &ctx)
|
stdVectorChildList(SymbolGroupNode *n, int count, const SymbolGroupValueContext &ctx)
|
||||||
{
|
{
|
||||||
if (count) {
|
if (!count)
|
||||||
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
|
// MSVC2012 has 2 base classes, MSVC2010 1, MSVC2008 none
|
||||||
|
const SymbolGroupValue vec = SymbolGroupValue(n, ctx);
|
||||||
|
SymbolGroupValue myFirst = SymbolGroupValue::findMember(vec, "_Myfirst");
|
||||||
|
if (!myFirst)
|
||||||
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
// std::vector<T>: _Myfirst is a pointer of T*. Get address
|
// std::vector<T>: _Myfirst is a pointer of T*. Get address
|
||||||
// element to obtain address.
|
// element to obtain address.
|
||||||
const SymbolGroupValue vec(n, ctx);
|
const ULONG64 address = myFirst.pointerValue();
|
||||||
SymbolGroupValue myFirst = vec[unsigned(0)]["_Myfirst"]; // MSVC2010
|
if (!address)
|
||||||
if (!myFirst)
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
myFirst = vec["_Myfirst"]; // MSVC2008
|
|
||||||
if (myFirst) {
|
|
||||||
if (const ULONG64 address = myFirst.pointerValue()) {
|
|
||||||
const std::string firstType = myFirst.type();
|
const std::string firstType = myFirst.type();
|
||||||
const std::string innerType = fixInnerType(SymbolGroupValue::stripPointerType(firstType), vec);
|
const std::string innerType = fixInnerType(SymbolGroupValue::stripPointerType(firstType), vec);
|
||||||
if (SymbolGroupValue::verbose)
|
if (SymbolGroupValue::verbose)
|
||||||
DebugPrint() << n->name() << " inner type: '" << innerType << "' from '" << firstType << '\'';
|
DebugPrint() << n->name() << " inner type: '" << innerType << "' from '" << firstType << '\'';
|
||||||
return arrayChildList(n->symbolGroup(), address, n->module(), innerType, count);
|
return arrayChildList(n->symbolGroup(), address, n->module(), innerType, count);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper for std::deque<>: From the array of deque blocks, read out the values.
|
// Helper for std::deque<>: From the array of deque blocks, read out the values.
|
||||||
template<class AddressType>
|
template<class AddressType>
|
||||||
@@ -399,17 +372,21 @@ AbstractSymbolGroupNodePtrVector
|
|||||||
|
|
||||||
// std::deque<>
|
// std::deque<>
|
||||||
static inline AbstractSymbolGroupNodePtrVector
|
static inline AbstractSymbolGroupNodePtrVector
|
||||||
stdDequeDirectChildList(const SymbolGroupValue &deque, int count)
|
stdDequeChildList(const SymbolGroupValue &dequeIn, int count)
|
||||||
{
|
{
|
||||||
if (!count)
|
if (!count)
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
// From MSVC10 on, there is an additional base class
|
// From MSVC10 on, there is an additional base class, MSVC2012 more.
|
||||||
const ULONG64 arrayAddress = deque["_Map"].pointerValue();
|
const SymbolGroupValue map = SymbolGroupValue::findMember(dequeIn, "_Map");
|
||||||
|
if (!map)
|
||||||
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
|
const SymbolGroupValue deque = map.parent();
|
||||||
|
const ULONG64 arrayAddress = map.pointerValue();
|
||||||
const int startOffset = deque["_Myoff"].intValue();
|
const int startOffset = deque["_Myoff"].intValue();
|
||||||
const int mapSize = deque["_Mapsize"].intValue();
|
const int mapSize = deque["_Mapsize"].intValue();
|
||||||
if (!arrayAddress || startOffset < 0 || mapSize <= 0)
|
if (!arrayAddress || startOffset < 0 || mapSize <= 0)
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
const std::vector<std::string> innerTypes = deque.innerTypes();
|
const std::vector<std::string> innerTypes = dequeIn.innerTypes();
|
||||||
if (innerTypes.empty())
|
if (innerTypes.empty())
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
const std::string innerType = fixInnerType(innerTypes.front(), deque);
|
const std::string innerType = fixInnerType(innerTypes.front(), deque);
|
||||||
@@ -435,15 +412,6 @@ static inline AbstractSymbolGroupNodePtrVector
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::deque<>
|
|
||||||
static inline AbstractSymbolGroupNodePtrVector
|
|
||||||
stdDequeChildList(const SymbolGroupValue &v, int count)
|
|
||||||
{
|
|
||||||
// MSVC10 has a base class. If that fails, try direct (MSVC2008)
|
|
||||||
const AbstractSymbolGroupNodePtrVector msvc10rc = stdDequeDirectChildList(v[unsigned(0)], count);
|
|
||||||
return msvc10rc.empty() ? stdDequeDirectChildList(v, count) : msvc10rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper class for std::map<>,std::set<> based on std::__Tree:
|
/* Helper class for std::map<>,std::set<> based on std::__Tree:
|
||||||
* We locally rebuild the structure in using instances of below class 'StdMapNode'
|
* We locally rebuild the structure in using instances of below class 'StdMapNode'
|
||||||
* with 'left' and 'right' pointers and the values. Reason being that while it is
|
* with 'left' and 'right' pointers and the values. Reason being that while it is
|
||||||
@@ -579,21 +547,20 @@ void StdMapNode::debug(std::ostream &os, unsigned depth) const
|
|||||||
// Helper for std::map<>,std::set<> based on std::__Tree:
|
// Helper for std::map<>,std::set<> based on std::__Tree:
|
||||||
// Return the list of children (pair for maps, direct children for set)
|
// Return the list of children (pair for maps, direct children for set)
|
||||||
static inline SymbolGroupValueVector
|
static inline SymbolGroupValueVector
|
||||||
stdTreeChildList(const SymbolGroupValue &tree, int count, bool *isMSVC2010In = 0)
|
stdTreeChildList(const SymbolGroupValue &treeIn, int count)
|
||||||
{
|
{
|
||||||
if (!count)
|
if (!count)
|
||||||
return SymbolGroupValueVector();
|
return SymbolGroupValueVector();
|
||||||
|
// MSVC2012: many base classes.
|
||||||
// MSVC2010: "class _Tree : public _Tree_val: public _Tree_nod".
|
// MSVC2010: "class _Tree : public _Tree_val: public _Tree_nod".
|
||||||
// MSVC2008: Direct class
|
// MSVC2008: Direct class
|
||||||
const int size = tree[unsigned(0)][unsigned(0)]["_Mysize"].intValue();
|
const SymbolGroupValue sizeV = SymbolGroupValue::findMember(treeIn, "_Mysize");
|
||||||
const bool isMSVC2010 = size >= 0 && size <= count; // Count may be limited
|
const SymbolGroupValue tree = sizeV.parent();
|
||||||
if (isMSVC2010In)
|
const int size = sizeV.intValue();
|
||||||
*isMSVC2010In = isMSVC2010;
|
if (!tree|| size <= 0)
|
||||||
const SymbolGroupValue treeNode = isMSVC2010 ? tree[unsigned(0)][unsigned(0)] : tree;
|
|
||||||
if (!treeNode)
|
|
||||||
return SymbolGroupValueVector();
|
return SymbolGroupValueVector();
|
||||||
// Build the tree and iterate it.
|
// Build the tree and iterate it.
|
||||||
const StdMapNode *nodeTree = StdMapNode::buildMap(treeNode);
|
const StdMapNode *nodeTree = StdMapNode::buildMap(tree);
|
||||||
if (!nodeTree)
|
if (!nodeTree)
|
||||||
return SymbolGroupValueVector();
|
return SymbolGroupValueVector();
|
||||||
SymbolGroupValueVector rc;
|
SymbolGroupValueVector rc;
|
||||||
@@ -611,7 +578,7 @@ static inline SymbolGroupValueVector
|
|||||||
static inline AbstractSymbolGroupNodePtrVector
|
static inline AbstractSymbolGroupNodePtrVector
|
||||||
stdSetChildList(const SymbolGroupValue &set, int count)
|
stdSetChildList(const SymbolGroupValue &set, int count)
|
||||||
{
|
{
|
||||||
const SymbolGroupValueVector children = stdTreeChildList(set[unsigned(0)], count);
|
const SymbolGroupValueVector children = stdTreeChildList(set, count);
|
||||||
if (int(children.size()) != count)
|
if (int(children.size()) != count)
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
AbstractSymbolGroupNodePtrVector rc;
|
AbstractSymbolGroupNodePtrVector rc;
|
||||||
@@ -625,17 +592,16 @@ static inline AbstractSymbolGroupNodePtrVector
|
|||||||
static inline AbstractSymbolGroupNodePtrVector
|
static inline AbstractSymbolGroupNodePtrVector
|
||||||
stdMapChildList(const SymbolGroupValue &map, int count)
|
stdMapChildList(const SymbolGroupValue &map, int count)
|
||||||
{
|
{
|
||||||
bool isMSVC2010 = true;
|
const SymbolGroupValueVector children = stdTreeChildList(map[unsigned(0)], count);
|
||||||
const SymbolGroupValueVector children = stdTreeChildList(map[unsigned(0)], count, &isMSVC2010);
|
|
||||||
if (int(children.size()) != count)
|
if (int(children.size()) != count)
|
||||||
return AbstractSymbolGroupNodePtrVector();
|
return AbstractSymbolGroupNodePtrVector();
|
||||||
AbstractSymbolGroupNodePtrVector rc;
|
AbstractSymbolGroupNodePtrVector rc;
|
||||||
rc.reserve(count);
|
rc.reserve(count);
|
||||||
|
const std::string firstName = "first";
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
// MSVC2010 introduces a std::pair_base.
|
// MSVC2010 (only) has a std::pair_base class.
|
||||||
const SymbolGroupValue pairBase = isMSVC2010?
|
const SymbolGroupValue key = SymbolGroupValue::findMember(children.at(i), firstName);
|
||||||
children.at(i)[unsigned(0)] : children.at(i);
|
const SymbolGroupValue pairBase = key.parent();
|
||||||
const SymbolGroupValue key = pairBase["first"];
|
|
||||||
const SymbolGroupValue value = pairBase["second"];
|
const SymbolGroupValue value = pairBase["second"];
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
rc.push_back(MapNodeSymbolGroupNode::create(i, pairBase.address(),
|
rc.push_back(MapNodeSymbolGroupNode::create(i, pairBase.address(),
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ DumpParameters::checkRecode(const std::string &type,
|
|||||||
DumpParameterRecodeResult result;
|
DumpParameterRecodeResult result;
|
||||||
if (SymbolGroupValue::verbose > 2) {
|
if (SymbolGroupValue::verbose > 2) {
|
||||||
DebugPrint debugPrint;
|
DebugPrint debugPrint;
|
||||||
debugPrint << '>' << __FUNCTION__ << ' ' << iname << '/' << iname;
|
debugPrint << '>' << __FUNCTION__ << ' ' << iname << '/' << type;
|
||||||
if (dp)
|
if (dp)
|
||||||
debugPrint << " option format: " << dp->format(type, iname);
|
debugPrint << " option format: " << dp->format(type, iname);
|
||||||
}
|
}
|
||||||
@@ -472,6 +472,9 @@ DumpParameters::checkRecode(const std::string &type,
|
|||||||
ULONG obtained = 0;
|
ULONG obtained = 0;
|
||||||
if (FAILED(ctx.dataspaces->ReadVirtual(address, result.buffer, ULONG(result.size), &obtained))) {
|
if (FAILED(ctx.dataspaces->ReadVirtual(address, result.buffer, ULONG(result.size), &obtained))) {
|
||||||
delete [] result.buffer;
|
delete [] result.buffer;
|
||||||
|
DebugPrint() << __FUNCTION__ << " ReadVirtual() failed to read "
|
||||||
|
<< result.size << " bytes from 0x" << std::hex
|
||||||
|
<< address << std::dec << " for " << iname << '.';
|
||||||
result = DumpParameterRecodeResult();
|
result = DumpParameterRecodeResult();
|
||||||
}
|
}
|
||||||
if (SymbolGroupValue::verbose > 2)
|
if (SymbolGroupValue::verbose > 2)
|
||||||
|
|||||||
@@ -126,6 +126,22 @@ SymbolGroupValue SymbolGroupValue::operator[](unsigned index) const
|
|||||||
return SymbolGroupValue(m_errorMessage);
|
return SymbolGroupValue(m_errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned SymbolGroupValue::childCount() const
|
||||||
|
{
|
||||||
|
if (ensureExpanded())
|
||||||
|
return unsigned(m_node->children().size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolGroupValue SymbolGroupValue::parent() const
|
||||||
|
{
|
||||||
|
if (isValid())
|
||||||
|
if (AbstractSymbolGroupNode *aParent = m_node->parent())
|
||||||
|
if (SymbolGroupNode *parent = aParent->asSymbolGroupNode())
|
||||||
|
return SymbolGroupValue(parent, m_context);
|
||||||
|
return SymbolGroupValue("parent() invoked on invalid value.");
|
||||||
|
}
|
||||||
|
|
||||||
bool SymbolGroupValue::ensureExpanded() const
|
bool SymbolGroupValue::ensureExpanded() const
|
||||||
{
|
{
|
||||||
if (!isValid() || !m_node->canExpand())
|
if (!isValid() || !m_node->canExpand())
|
||||||
@@ -205,7 +221,7 @@ int SymbolGroupValue::intValue(int defaultValue) const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (SymbolGroupValue::verbose)
|
if (SymbolGroupValue::verbose)
|
||||||
DebugPrint() << name() << "::intValue() fails";
|
DebugPrint() << name() << '/' << type() << '/'<< m_errorMessage << ": intValue() fails";
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +233,7 @@ ULONG64 SymbolGroupValue::pointerValue(ULONG64 defaultValue) const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (SymbolGroupValue::verbose)
|
if (SymbolGroupValue::verbose)
|
||||||
DebugPrint() << name() << "::pointerValue() fails";
|
DebugPrint() << name() << '/'<< type() << '/' << m_errorMessage << ": pointerValue() fails";
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,6 +399,30 @@ SymbolGroupValue SymbolGroupValue::typeCastedValue(ULONG64 address, const char *
|
|||||||
return SymbolGroupValue();
|
return SymbolGroupValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolGroupValue SymbolGroupValue::findMember(const SymbolGroupValue &start,
|
||||||
|
const std::string &symbolName)
|
||||||
|
{
|
||||||
|
const unsigned count = start.childCount();
|
||||||
|
for (unsigned i = 0; i < count ; ++i) { // check members
|
||||||
|
const SymbolGroupValue child = start[i];
|
||||||
|
if (child.name() == symbolName)
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
// Recurse down base classes at the beginning that have class names
|
||||||
|
// as value.
|
||||||
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
|
const SymbolGroupValue child = start[i];
|
||||||
|
const std::wstring value = child.value();
|
||||||
|
if (value.compare(0, 6, L"class ") && value.compare(0, 7, L"struct ")) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (SymbolGroupValue r = findMember(child, symbolName))
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SymbolGroupValue();
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring SymbolGroupValue::wcharPointerData(unsigned charCount, unsigned maxCharCount) const
|
std::wstring SymbolGroupValue::wcharPointerData(unsigned charCount, unsigned maxCharCount) const
|
||||||
{
|
{
|
||||||
const bool truncated = charCount > maxCharCount;
|
const bool truncated = charCount > maxCharCount;
|
||||||
@@ -2047,14 +2087,10 @@ static inline bool dumpQWindow(const SymbolGroupValue &v, std::wostream &str, vo
|
|||||||
// Dump a std::string.
|
// Dump a std::string.
|
||||||
static bool dumpStd_W_String(const SymbolGroupValue &v, int type, std::wostream &str)
|
static bool dumpStd_W_String(const SymbolGroupValue &v, int type, std::wostream &str)
|
||||||
{
|
{
|
||||||
SymbolGroupValue bx = v[unsigned(0)]["_Bx"];
|
// Find 'bx'. MSVC 2012 has 2 base classes, MSVC 2010 1,
|
||||||
int reserved = 0;
|
// and MSVC2008 none
|
||||||
if (bx) { // MSVC 2010
|
const SymbolGroupValue bx = SymbolGroupValue::findMember(v, "_Bx");
|
||||||
reserved = v[unsigned(0)]["_Myres"].intValue();
|
const int reserved = bx.parent()["_Myres"].intValue();
|
||||||
} else { // MSVC2008
|
|
||||||
bx = v["_Bx"];
|
|
||||||
reserved = v["_Myres"].intValue();
|
|
||||||
}
|
|
||||||
if (!bx || reserved < 0)
|
if (!bx || reserved < 0)
|
||||||
return false;
|
return false;
|
||||||
// 'Buf' array for small strings, else pointer 'Ptr'.
|
// 'Buf' array for small strings, else pointer 'Ptr'.
|
||||||
|
|||||||
@@ -68,11 +68,17 @@ public:
|
|||||||
// Access children by name or index (0-based)
|
// Access children by name or index (0-based)
|
||||||
SymbolGroupValue operator[](const char *name) const;
|
SymbolGroupValue operator[](const char *name) const;
|
||||||
SymbolGroupValue operator[](unsigned) const;
|
SymbolGroupValue operator[](unsigned) const;
|
||||||
|
unsigned childCount() const;
|
||||||
|
SymbolGroupValue parent() const;
|
||||||
// take address and cast to desired (pointer) type
|
// take address and cast to desired (pointer) type
|
||||||
SymbolGroupValue typeCast(const char *type) const;
|
SymbolGroupValue typeCast(const char *type) const;
|
||||||
// take pointer value and cast to desired (pointer) type
|
// take pointer value and cast to desired (pointer) type
|
||||||
SymbolGroupValue pointerTypeCast(const char *type) const;
|
SymbolGroupValue pointerTypeCast(const char *type) const;
|
||||||
|
// Find a member variable traversing the list of base classes. This useful
|
||||||
|
// for skipping template base classes of STL containers whose number varies
|
||||||
|
// by MSVC version.
|
||||||
|
static SymbolGroupValue findMember(const SymbolGroupValue &start,
|
||||||
|
const std::string &symbolName);
|
||||||
std::string name() const;
|
std::string name() const;
|
||||||
std::string type() const;
|
std::string type() const;
|
||||||
std::vector<std::string> innerTypes() const { return innerTypesOf(type()); }
|
std::vector<std::string> innerTypes() const { return innerTypesOf(type()); }
|
||||||
|
|||||||
Reference in New Issue
Block a user