From edacb7d3833b8b14ba2b42d1697793b0fc83963e Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 27 Feb 2017 14:04:32 +0100 Subject: [PATCH] Debugger: Use symbol tag to determine type code Change-Id: I49a2a0f3e1ff65accb0d2e04fbd9352ce3f63f2c Reviewed-by: Christian Stenger --- share/qtcreator/debugger/cdbbridge.py | 12 ++++- src/libs/qtcreatorcdbext/pytype.cpp | 64 +++++++++++++++++++++------ src/libs/qtcreatorcdbext/pytype.h | 4 +- src/libs/qtcreatorcdbext/pyvalue.cpp | 36 +++++++++++++-- src/libs/qtcreatorcdbext/pyvalue.h | 3 ++ 5 files changed, 98 insertions(+), 21 deletions(-) diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index ef202148c81..c7b38ac9d1d 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -149,10 +149,18 @@ class Dumper(DumperBase): code = nativeType.code() if code == TypeCodePointer: - return self.createPointerType(self.lookupType(nativeType.targetName(), nativeType.moduleId())) + if nativeType.name().startswith(''): + code = TypeCodeFunction + else: + targetType = self.lookupType(nativeType.targetName(), nativeType.moduleId()) + return self.createPointerType(targetType) if code == TypeCodeArray: - return self.createArrayType(self.lookupType(nativeType.targetName(), nativeType.moduleId()), nativeType.arrayElements()) + if nativeType.name().startswith('__fptr()'): + code = TypeCodeStruct + else: + targetType = self.lookupType(nativeType.targetName(), nativeType.moduleId()) + return self.createArrayType(targetType, nativeType.arrayElements()) tdata = self.TypeData(self) tdata.name = nativeType.name() diff --git a/src/libs/qtcreatorcdbext/pytype.cpp b/src/libs/qtcreatorcdbext/pytype.cpp index d984d1c8be7..2525a65114e 100644 --- a/src/libs/qtcreatorcdbext/pytype.cpp +++ b/src/libs/qtcreatorcdbext/pytype.cpp @@ -27,9 +27,19 @@ #include "extensioncontext.h" #include "pycdbextmodule.h" +#include "pyvalue.h" #include "stringutils.h" #include "symbolgroupvalue.h" +#include +#ifndef _NO_CVCONST_H +#define _NO_CVCONST_H +#include +#undef _NO_CVCONST_H +#else +#include +#endif + constexpr bool debugPyType = false; constexpr bool debuggingTypeEnabled() { return debugPyType || debugPyCdbextModule; } @@ -202,10 +212,11 @@ static std::string getModuleName(ULONG64 module) return std::string(); } -PyType::PyType(ULONG64 module, unsigned long typeId, const std::string &name) +PyType::PyType(ULONG64 module, unsigned long typeId, const std::string &name, int tag) : m_module(module) , m_typeId(typeId) , m_resolved(true) + , m_tag(tag) { m_name = SymbolGroupValue::stripClassPrefixes(name); if (m_name.compare(0, 6, "union ") == 0) @@ -257,19 +268,44 @@ int PyType::code() const { if (!m_resolved) return TypeCodeUnresolvable; - const std::string &typeName = name(); - if (typeName.empty()) - return TypeCodeUnresolvable; - if (isPointerType(typeName)) - return TypeCodePointer; - if (isArrayType(typeName)) - return TypeCodeArray; - if (typeName.find("") != std::string::npos) - return TypeCodeFunction; - if (isIntegralType(typeName)) - return TypeCodeIntegral; - if (isFloatType(typeName)) - return TypeCodeFloat; + + if (m_tag < 0) { + // try to parse typeName + const std::string &typeName = name(); + if (typeName.empty()) + return TypeCodeUnresolvable; + if (isPointerType(typeName)) + return TypeCodePointer; + if (isArrayType(typeName)) + return TypeCodeArray; + if (typeName.find("") == 0) + return TypeCodeFunction; + if (isIntegralType(typeName)) + return TypeCodeIntegral; + if (isFloatType(typeName)) + return TypeCodeFloat; + + IDebugSymbolGroup2 *sg = 0; + if (FAILED(ExtensionCommandContext::instance()->symbols()->CreateSymbolGroup2(&sg))) + return TypeCodeStruct; + + const std::string helperValueName = SymbolGroupValue::pointedToSymbolName(0, name(true)); + ULONG index = DEBUG_ANY_ID; + if (SUCCEEDED(sg->AddSymbol(helperValueName.c_str(), &index))) + m_tag = PyValue(index, sg).tag(); + sg->Release(); + } + switch (m_tag) { + case SymTagUDT: return TypeCodeStruct; + case SymTagEnum: return TypeCodeEnum; + case SymTagTypedef: return TypeCodeTypedef; + case SymTagFunctionType: return TypeCodeFunction; + case SymTagPointerType: return TypeCodePointer; + case SymTagArrayType: return TypeCodeArray; + case SymTagBaseType: return isIntegralType(name()) ? TypeCodeIntegral : TypeCodeFloat; + default: break; + } + return TypeCodeStruct; } diff --git a/src/libs/qtcreatorcdbext/pytype.h b/src/libs/qtcreatorcdbext/pytype.h index fe0c2e5f3e5..68acda25ba8 100644 --- a/src/libs/qtcreatorcdbext/pytype.h +++ b/src/libs/qtcreatorcdbext/pytype.h @@ -36,7 +36,8 @@ class PyType { public: PyType() = default; - PyType(ULONG64 module, unsigned long typeId, const std::string &name = std::string()); + PyType(ULONG64 module, unsigned long typeId, + const std::string &name = std::string(), int tag = -1); PyType(const PyType &other) = default; std::string name(bool withModule = false) const; @@ -75,6 +76,7 @@ private: ULONG64 m_module = 0; bool m_resolved = false; mutable std::string m_name; + mutable int m_tag = -1; }; struct TypePythonObject diff --git a/src/libs/qtcreatorcdbext/pyvalue.cpp b/src/libs/qtcreatorcdbext/pyvalue.cpp index 9ecc57e3807..a786c2d9af6 100644 --- a/src/libs/qtcreatorcdbext/pyvalue.cpp +++ b/src/libs/qtcreatorcdbext/pyvalue.cpp @@ -85,12 +85,13 @@ PyType PyValue::type() return PyType(); ULONG size = 0; m_symbolGroup->GetSymbolTypeName(m_index, NULL, 0, &size); + std::string typeName; if (size != 0) { - std::string typeName(size - 1, '\0'); - if (SUCCEEDED(m_symbolGroup->GetSymbolTypeName(m_index, &typeName[0], size, NULL))) - return PyType(params.Module, params.TypeId, typeName); + typeName = std::string(size - 1, '\0'); + if (FAILED(m_symbolGroup->GetSymbolTypeName(m_index, &typeName[0], size, NULL))) + typeName.clear(); } - return PyType(params.Module, params.TypeId); + return PyType(params.Module, params.TypeId, typeName, tag()); } ULONG64 PyValue::bitsize() @@ -188,6 +189,16 @@ int PyValue::isValid() return m_symbolGroup != nullptr; } +int PyValue::tag() +{ + if (!m_symbolGroup) + return -1; + DEBUG_SYMBOL_ENTRY info; + if (FAILED(m_symbolGroup->GetSymbolEntryInformation(m_index, &info))) + return -1; + return info.Tag; +} + PyValue PyValue::childFromName(const std::string &name) { const ULONG endIndex = m_index + childCount(); @@ -301,6 +312,23 @@ PyValue PyValue::createValue(ULONG64 address, const PyType &type) return PyValue(index, symbolGroup); } +int PyValue::tag(const std::string &typeName) +{ + CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols(); + IDebugSymbolGroup2 *sg = 0; + if (FAILED(symbols->CreateSymbolGroup2(&sg))) + return -1; + + int tag = -1; + const std::string name = SymbolGroupValue::pointedToSymbolName(0, typeName); + ULONG index = DEBUG_ANY_ID; + if (SUCCEEDED(sg->AddSymbol(name.c_str(), &index))) + tag = PyValue(index, sg).tag(); + + sg->Release(); + return tag; +} + // Python interface implementation namespace PyValueInterface { diff --git a/src/libs/qtcreatorcdbext/pyvalue.h b/src/libs/qtcreatorcdbext/pyvalue.h index 9d2cae9443f..fd009b2ff8c 100644 --- a/src/libs/qtcreatorcdbext/pyvalue.h +++ b/src/libs/qtcreatorcdbext/pyvalue.h @@ -49,12 +49,15 @@ public: std::string nativeDebuggerValue(); int isValid(); + int tag(); PyValue childFromName(const std::string &name); PyValue childFromField(const PyField &field); PyValue childFromIndex(int index); static PyValue createValue(ULONG64 address, const PyType &type); + static int tag(const std::string &typeName); + private: static void indicesMoved(CIDebugSymbolGroup *symbolGroup, ULONG start, ULONG delta);