diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index 9b665e066ba..827502e1708 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -131,36 +131,35 @@ class Dumper(DumperBase): tdata.lbitsize = nativeType.bitsize() tdata.code = code self.registerType(typeId, tdata) # Prevent recursion in fields. - tdata.lfields = self.listFields(nativeType, self.Type(self, typeId)) + if code == TypeCodeStruct: + tdata.lfields = lambda value : \ + self.listFields(nativeType, value) + tdata.lalignment = lambda : \ + self.nativeStructAlignment(nativeType) tdata.templateArguments = self.listTemplateParameters(nativeType) self.registerType(typeId, tdata) # Fix up fields and template args return self.Type(self, typeId) - def listFields(self, nativeType, parentType): - fields = [] + def listFields(self, nativeType, value): + if value.address() is None or value.address() == 0: + raise Exception("") + nativeValue = cdbext.createValue(value.address(), nativeType) + index = 0 + nativeMember = nativeValue.childFromIndex(index) + while nativeMember is not None: + yield self.fromNativeValue(nativeMember) + index += 1 + nativeMember = nativeValue.childFromIndex(index) - if not nativeType.code() == TypeCodeStruct: - return fields - - nativeIndex = 0 - nativeFields = nativeType.fields() - for nativeField in nativeFields: - field = self.Field(self) - fieldType = nativeField.type().unqualified() - if fieldType is None: - fieldType = FakeVoidType('void', self) - field.ltype = self.fromNativeType(fieldType) - field.parentType = parentType - field.name = nativeField.name() - field.isBaseClass = False - field.lbitpos = nativeField.bitpos() - field.lbitsize = nativeField.bitsize() - field.nativeIndex = nativeIndex - #warn("FIELD RESULT: %s" % field) - fields.append(field) - nativeIndex += 1 - - return fields + def nativeStructAlignment(self, nativeType): + #warn("NATIVE ALIGN FOR %s" % nativeType.name) + def handleItem(nativeFieldType, align): + a = self.fromNativeType(nativeFieldType).alignment() + return a if a > align else align + align = 1 + for f in nativeType.fields(): + align = handleItem(f.type(), align) + return align def listTemplateParameters(self, nativeType): targs = [] diff --git a/src/libs/qtcreatorcdbext/pycdbextmodule.cpp b/src/libs/qtcreatorcdbext/pycdbextmodule.cpp index baced0b15ab..3cee368e1ea 100644 --- a/src/libs/qtcreatorcdbext/pycdbextmodule.cpp +++ b/src/libs/qtcreatorcdbext/pycdbextmodule.cpp @@ -27,6 +27,7 @@ #include "extensioncontext.h" #include "symbolgroup.h" +#include "symbolgroupvalue.h" #include "pyfield.h" #include "pystdoutredirect.h" @@ -106,6 +107,57 @@ static PyObject *cdbext_readRawMemory(PyObject *, PyObject *args) return ret; } +static PyObject *cdbext_createValue(PyObject *, PyObject *args) +{ + ULONG64 address = 0; + Type *type = 0; + if (!PyArg_ParseTuple(args, "KO", &address, &type)) + Py_RETURN_NONE; + + if (debugPyCdbextModule) { + DebugPrint() << "Create Value address: 0x" << std::hex << address + << " type name: " << getTypeName(type->m_module, type->m_typeId); + } + + ExtensionCommandContext *extCmdCtx = ExtensionCommandContext::instance(); + CIDebugSymbols *symbols = extCmdCtx->symbols(); + + ULONG frame; + if (FAILED(symbols->GetCurrentScopeFrameIndex(&frame))) + Py_RETURN_NONE; + + std::string errorMessage; + LocalsSymbolGroup *lsg = ExtensionContext::instance().symbolGroup( + symbols, extCmdCtx->threadId(), int(frame), &errorMessage); + if (!lsg) + Py_RETURN_NONE; + + CIDebugSymbolGroup *dsg = lsg->debugSymbolGroup(); + ULONG numberOfSymbols = 0; + dsg->GetNumberSymbols(&numberOfSymbols); + ULONG index = 0; + for (;index < numberOfSymbols; ++index) { + ULONG64 offset; + dsg->GetSymbolOffset(index, &offset); + if (offset == address) { + DEBUG_SYMBOL_PARAMETERS params; + if (SUCCEEDED(dsg->GetSymbolParameters(index, 1, ¶ms))) { + if (params.TypeId == type->m_typeId && params.Module == type->m_module) + break; + } + } + } + + if (index >= numberOfSymbols) { + index = DEBUG_ANY_ID; + const std::string name = SymbolGroupValue::pointedToSymbolName( + address, getTypeName(type->m_module, type->m_typeId)); + if (FAILED(dsg->AddSymbol(name.c_str(), &index))) + Py_RETURN_NONE; + } + return createValue(index, dsg); +} + static PyMethodDef cdbextMethods[] = { {"parseAndEvaluate", cdbext_parseAndEvaluate, METH_VARARGS, "Returns value of expression or None if the expression can not be resolved"}, @@ -117,6 +169,8 @@ static PyMethodDef cdbextMethods[] = { "Returns the size of a pointer"}, {"readRawMemory", cdbext_readRawMemory, METH_VARARGS, "Read a block of data from the virtual address space"}, + {"createValue", cdbext_createValue, METH_VARARGS, + "Creates a value with the given type at the given address"}, {NULL, NULL, 0, NULL} /* Sentinel */ };