diff options
Diffstat (limited to 'share/qtcreator/debugger/lldbbridge.py')
-rw-r--r-- | share/qtcreator/debugger/lldbbridge.py | 606 |
1 files changed, 334 insertions, 272 deletions
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index b64d115a0a8..6b08ac3d322 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -116,33 +116,29 @@ class Dumper(DumperBase): self.isInterrupting_ = False self.interpreterBreakpointResolvers = [] - DumperBase.warn = Dumper.warn_impl self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString()) - @staticmethod - def warn_impl(message): - if message[-1:] == '\n': - message += '\n' + def warn(self, msg): + #self.put('{name="%s",value="",type="",numchild="0"},' % toCString(msg)) + if msg[-1:] == '\n': + msg += '\n' print('@\nbridgemessage={msg="%s",channel="%s"}\n@' - % (message.replace('"', '$'), LogChannel.AppError)) - - def fromNativeFrameValue(self, nativeValue): - return self.fromNativeValue(nativeValue) + % (msg.replace('"', '$'), LogChannel.AppError)) def fromNativeValue(self, nativeValue): self.check(isinstance(nativeValue, lldb.SBValue)) nativeType = nativeValue.GetType() - typeName = nativeType.GetName() + type_name = nativeType.GetName() code = nativeType.GetTypeClass() # Display the result of GetSummary() for Core Foundation string # and string-like types. summary = None if self.useFancy: - if (typeName.startswith('CF') - or typeName.startswith('__CF') - or typeName.startswith('NS') - or typeName.startswith('__NSCF')): + if (type_name.startswith('CF') + or type_name.startswith('__CF') + or type_name.startswith('NS') + or type_name.startswith('__NSCF')): if code == lldb.eTypeClassPointer: summary = nativeValue.Dereference().GetSummary() elif code == lldb.eTypeClassReference: @@ -156,26 +152,26 @@ class Dumper(DumperBase): nativeTargetType = nativeType.GetDereferencedType() if not nativeTargetType.IsPointerType(): nativeTargetType = nativeTargetType.GetUnqualifiedType() - targetType = self.fromNativeType(nativeTargetType) - val = self.createReferenceValue(nativeValue.GetValueAsUnsigned(), targetType) + target_typeid = self.from_native_type(nativeTargetType) + target_address = nativeValue.GetValueAsUnsigned() + val = self.Value(self) + val.ldata = target_address.to_bytes(self.ptrSize(), 'little') + if self.useDynamicType: + target_typeid = self.dynamic_typeid_at_address(target_typeid, target_address) + val.typeid = self.create_reference_typeid(target_typeid) val.laddress = nativeValue.AddressOf().GetValueAsUnsigned() - #DumperBase.warn('CREATED REF: %s' % val) + #self.warn('CREATED REF: %s' % val) + elif code == lldb.eTypeClassPointer: nativeTargetType = nativeType.GetPointeeType() if not nativeTargetType.IsPointerType(): nativeTargetType = nativeTargetType.GetUnqualifiedType() - targetType = self.fromNativeType(nativeTargetType) - val = self.createPointerValue(nativeValue.GetValueAsUnsigned(), targetType) - #DumperBase.warn('CREATED PTR 1: %s' % val) + target_typeid = self.from_native_type(nativeTargetType) + val = self.Value(self) + val.ldata = nativeValue.GetValueAsUnsigned() + val.typeid = self.create_pointer_typeid(target_typeid) val.laddress = nativeValue.AddressOf().GetValueAsUnsigned() - #DumperBase.warn('CREATED PTR 2: %s' % val) - elif code == lldb.eTypeClassTypedef: - nativeTargetType = nativeType.GetUnqualifiedType() - if hasattr(nativeTargetType, 'GetCanonicalType'): - nativeTargetType = nativeTargetType.GetCanonicalType() - val = self.fromNativeValue(nativeValue.Cast(nativeTargetType)) - val._type = self.fromNativeType(nativeType) - #DumperBase.warn('CREATED TYPEDEF: %s' % val) + else: val = self.Value(self) address = nativeValue.GetLoadAddress() @@ -193,7 +189,7 @@ class Dumper(DumperBase): except: pass - val._type = self.fromNativeType(nativeType) + val.typeid = self.from_native_type(nativeType) if code == lldb.eTypeClassEnumeration: intval = nativeValue.GetValueAsSigned() @@ -209,43 +205,32 @@ class Dumper(DumperBase): val.ldisplay = str(nativeValue.GetValue()) #elif code == lldb.eTypeClassArray: # if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x - # val.type.ltarget = self.fromNativeType(nativeType.GetArrayElementType()) + # val.type.ltarget = self.from_native_type(nativeType.GetArrayElementType()) # else: # fields = nativeType.get_fields_array() # if len(fields): - # val.type.ltarget = self.fromNativeType(fields[0]) + # val.type.ltarget = self.from_native_type(fields[0]) #elif code == lldb.eTypeClassVector: - # val.type.ltarget = self.fromNativeType(nativeType.GetVectorElementType()) + # val.type.ltarget = self.from_native_type(nativeType.GetVectorElementType()) val.summary = summary val.lIsInScope = nativeValue.IsInScope() val.name = nativeValue.GetName() return val - def nativeStructAlignment(self, nativeType): - def handleItem(nativeFieldType, align): - a = self.fromNativeType(nativeFieldType).alignment() - return a if a > align else align - align = 1 - for i in range(nativeType.GetNumberOfDirectBaseClasses()): - base = nativeType.GetDirectBaseClassAtIndex(i) - align = handleItem(base.GetType(), align) - for i in range(nativeType.GetNumberOfFields()): - child = nativeType.GetFieldAtIndex(i) - align = handleItem(child.GetType(), align) - return align - - def listMembers(self, value, nativeType): - #DumperBase.warn("ADDR: 0x%x" % self.fakeAddress_) - if value.laddress: - fakeAddress = lldb.SBAddress(value.laddress, self.target) - fakeLAddress = value.laddress - else: - fakeAddress = self.fakeAddress_ - fakeLAddress = self.fakeLAddress_ + def nativeListMembers(self, value, nativeType, include_base): + #self.warn("ADDR: 0x%x" % self.fakeAddress_) + nativeValue = value.nativeValue + if nativeValue is None: + if value.laddress: + fakeAddress = lldb.SBAddress(value.laddress, self.target) + fakeLAddress = value.laddress + else: + fakeAddress = self.fakeAddress_ + fakeLAddress = self.fakeLAddress_ + nativeValue = self.target.CreateValueFromAddress('x', fakeAddress, nativeType) - fakeValue = self.target.CreateValueFromAddress('x', fakeAddress, nativeType) - fakeValue.SetPreferSyntheticValue(False) + nativeValue.SetPreferSyntheticValue(False) baseNames = {} for i in range(nativeType.GetNumberOfDirectBaseClasses()): @@ -262,86 +247,99 @@ class Dumper(DumperBase): # Normal members and non-empty base classes. anonNumber = 0 - for i in range(fakeValue.GetNumChildren()): - nativeField = fakeValue.GetChildAtIndex(i) + + fields = [] + for i in range(nativeValue.GetNumChildren()): + nativeField = nativeValue.GetChildAtIndex(i) nativeField.SetPreferSyntheticValue(False) fieldName = nativeField.GetName() nativeFieldType = nativeField.GetType() if fieldName in fieldBits: - (fieldBitsize, fieldBitpos, isBitfield) = fieldBits[fieldName] + (bitsize, bitpos, isBitfield) = fieldBits[fieldName] else: - fieldBitsize = nativeFieldType.GetByteSize() * 8 - fieldBitpos = None + bitsize = nativeFieldType.GetByteSize() * 8 + bitpos = None isBitfield = False if isBitfield: # Bit fields - fieldType = self.createBitfieldType( - self.createType(self.typeName(nativeFieldType)), fieldBitsize) - yield self.Field(self, name=fieldName, type=fieldType, - bitsize=fieldBitsize, bitpos=fieldBitpos) + field_typeid = self.create_bitfield_typeid( + self.create_typeid(nativeFieldType.GetName()), bitsize) + val = self.Value(self) + val.name = fieldName + val.isBaseClass = False + val.typeid = field_typeid + val.ldata = self.value_extract_bits(value, bitpos, bitsize) + val.laddress = None + fields.append(val) elif fieldName is None: # Anon members anonNumber += 1 fieldName = '#%s' % anonNumber - fakeMember = fakeValue.GetChildAtIndex(i) + fakeMember = nativeValue.GetChildAtIndex(i) fakeMemberAddress = fakeMember.GetLoadAddress() - offset = fakeMemberAddress - fakeLAddress - yield self.Field(self, name=fieldName, type=self.fromNativeType(nativeFieldType), - bitsize=fieldBitsize, bitpos=8 * offset) + val = self.Value(self) + val.name = fieldName + val.isBaseClass = False + val.typeid = typeid=self.from_native_type(nativeFieldType) + field_offset = fakeMemberAddress - fakeLAddress + if value.laddress is not None: + val.laddress = value.laddress + field_offset + if value.ldata is not None: + field_size = (bitsize + 7) // 8 + val.ldata = value.ldata[field_offset:field_offset + field_size] + fields.append(val) elif fieldName in baseNames: # Simple bases - member = self.fromNativeValue(fakeValue.GetChildAtIndex(i)) + member = self.fromNativeValue(nativeValue.GetChildAtIndex(i)) member.isBaseClass = True - yield member + fields.append(member) else: # Normal named members - member = self.fromNativeValue(fakeValue.GetChildAtIndex(i)) + member = self.fromNativeValue(nativeValue.GetChildAtIndex(i)) member.name = nativeField.GetName() - yield member - - # Empty bases are not covered above. - for i in range(nativeType.GetNumberOfDirectBaseClasses()): - fieldObj = nativeType.GetDirectBaseClassAtIndex(i) - fieldType = fieldObj.GetType() - if fieldType.GetNumberOfFields() == 0: - if fieldType.GetNumberOfDirectBaseClasses() == 0: - member = self.Value(self) - fieldName = fieldObj.GetName() - member._type = self.fromNativeType(fieldType) - member.name = fieldName - member.fields = [] - if False: - # This would be correct if we came here only for - # truly empty base classes. Alas, we don't, see below. - member.ldata = bytes() - member.lbitsize = fieldType.GetByteSize() * 8 - else: - # This is a hack. LLDB 3.8 reports declared but not defined - # types as having no fields and(!) size == 1. At least - # for the common case of a single base class we can - # fake the contents by using the whole derived object's - # data as base class data. - data = fakeValue.GetData() - size = nativeType.GetByteSize() - member.lbitsize = size * 8 - error = lldb.SBError() - member.laddress = value.laddress - member.ldata = data.ReadRawData(error, 0, size) - member.isBaseClass = True - member.ltype = self.fromNativeType(fieldType) - member.name = fieldName - yield member + fields.append(member) + + + if include_base: + # Empty bases are not covered above. + for i in range(nativeType.GetNumberOfDirectBaseClasses()): + fieldObj = nativeType.GetDirectBaseClassAtIndex(i) + fieldType = fieldObj.GetType() + if fieldType.GetNumberOfFields() == 0: + if fieldType.GetNumberOfDirectBaseClasses() == 0: + member = self.Value(self) + fieldName = fieldObj.GetName() + member.typeid = self.from_native_type(fieldType) + member.name = fieldName + member.fields = [] + if False: + # This would be correct if we came here only for + # truly empty base classes. Alas, we don't, see below. + member.ldata = bytes() + else: + # This is a hack. LLDB 3.8 reports declared but not defined + # types as having no fields and(!) size == 1. At least + # for the common case of a single base class we can + # fake the contents by using the whole derived object's + # data as base class data. + data = nativeValue.GetData() + size = nativeType.GetByteSize() + error = lldb.SBError() + member.laddress = value.laddress + member.ldata = data.ReadRawData(error, 0, size) + member.isBaseClass = True + fields.append(member) + return fields def ptrSize(self): result = self.target.GetAddressByteSize() self.ptrSize = lambda: result return result - def fromNativeType(self, nativeType): + def from_native_type(self, nativeType): self.check(isinstance(nativeType, lldb.SBType)) - code = nativeType.GetTypeClass() # eTypeClassInvalid = (0u), # eTypeClassArray = (1u << 0), @@ -367,43 +365,41 @@ class Dumper(DumperBase): # // Define a mask that can be used for any type when finding types # eTypeClassAny = (0xffffffffu) - #DumperBase.warn('CURRENT: %s' % self.typeData.keys()) - #DumperBase.warn('FROM NATIVE TYPE: %s' % nativeType.GetName()) - if code == lldb.eTypeClassInvalid: - return None + #self.warn('CURRENT: %s' % self.typeData.keys()) + #self.warn('FROM NATIVE TYPE: %s' % nativeType.GetName()) - if code == lldb.eTypeClassBuiltin: - nativeType = nativeType.GetUnqualifiedType() + typeid_str = self.native_type_key(nativeType) + known_typeid = self.typeid_from_typekey.get(typeid_str, None) + if known_typeid is not None: + return known_typeid - if code == lldb.eTypeClassPointer: - #DumperBase.warn('PTR') - nativeTargetType = nativeType.GetPointeeType() - if not nativeTargetType.IsPointerType(): - nativeTargetType = nativeTargetType.GetUnqualifiedType() - #DumperBase.warn('PTR: %s' % nativeTargetType.name) - return self.createPointerType(self.fromNativeType(nativeTargetType)) + code = nativeType.GetTypeClass() - if code == lldb.eTypeClassReference: + if code == lldb.eTypeClassInvalid: + typeid = 0 + + elif code == lldb.eTypeClassPointer: + #self.warn('PTR: %s' % nativeTargetType.name) + target_typeid = self.from_native_type(nativeType.GetPointeeType()) + typeid = self.create_pointer_typeid(target_typeid) + + elif code == lldb.eTypeClassReference: #DumperBase.warn('REF') - nativeTargetType = nativeType.GetDereferencedType() - if not nativeTargetType.IsPointerType(): - nativeTargetType = nativeTargetType.GetUnqualifiedType() - #DumperBase.warn('REF: %s' % nativeTargetType.name) - return self.createReferenceType(self.fromNativeType(nativeTargetType)) + target_typeid = self.from_native_type(nativeType.GetDereferencedType()) + typeid = self.create_reference_typeid(target_typeid) - if code == lldb.eTypeClassTypedef: + elif code == lldb.eTypeClassTypedef: #DumperBase.warn('TYPEDEF') nativeTargetType = nativeType.GetUnqualifiedType() if hasattr(nativeTargetType, 'GetCanonicalType'): nativeTargetType = nativeTargetType.GetCanonicalType() - targetType = self.fromNativeType(nativeTargetType) - return self.createTypedefedType(targetType, nativeType.GetName(), - self.nativeTypeId(nativeType)) - - nativeType = nativeType.GetUnqualifiedType() - typeName = self.typeName(nativeType) + target_typeid = self.from_native_type(nativeTargetType) + typeid = self.create_typedefed_typeid(target_typeid, nativeType.GetName(), + typeid_str) - if code in (lldb.eTypeClassArray, lldb.eTypeClassVector): + elif code in (lldb.eTypeClassArray, lldb.eTypeClassVector): + nativeType = nativeType.GetUnqualifiedType() + type_name = nativeType.GetName() #DumperBase.warn('ARRAY: %s' % nativeType.GetName()) if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x nativeTargetType = nativeType.GetArrayElementType() @@ -412,141 +408,139 @@ class Dumper(DumperBase): #DumperBase.warn('BAD: %s ' % nativeTargetType.get_fields_array()) nativeTargetType = nativeType.GetVectorElementType() count = nativeType.GetByteSize() // nativeTargetType.GetByteSize() - targetTypeName = nativeTargetType.GetName() - if targetTypeName.startswith('(anon'): - typeName = nativeType.GetName() - pos1 = typeName.rfind('[') - targetTypeName = typeName[0:pos1].strip() - #DumperBase.warn("TARGET TYPENAME: %s" % targetTypeName) - targetType = self.fromNativeType(nativeTargetType) - targetType.setTdata(targetType.tdata.copy()) - targetType.tdata.name = targetTypeName - return self.createArrayType(targetType, count) - if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x + target_typename = nativeTargetType.GetName() + if target_typename.startswith('(anon'): + type_name = nativeType.GetName() + pos1 = type_name.rfind('[') + target_typename = type_name[0:pos1].strip() + #DumperBase.warn("TARGET TYPENAME: %s" % target_typename) + target_typeid = self.from_native_type(nativeTargetType) + #target_typeid.setTdata(target_typeid.tdata.copy()) + #target_typeid.tdata.name = target_typename + typeid = self.create_array_typeid(target_typeid, count) + elif hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x nativeTargetType = nativeType.GetVectorElementType() count = nativeType.GetByteSize() // nativeTargetType.GetByteSize() - targetType = self.fromNativeType(nativeTargetType) - return self.createArrayType(targetType, count) - return self.createType(nativeType.GetName()) + target_typeid = self.from_native_type(nativeTargetType) + typeid = self.create_array_typeid(target_typeid, count) + else: + typeid = self.create_type(nativeType.GetName()) + + else: + nativeType = nativeType.GetUnqualifiedType() + type_name = nativeType.GetName() - typeId = self.nativeTypeId(nativeType) - res = self.typeData.get(typeId, None) - if res is None: + typeid = self.typeid_for_string(typeid_str) + #if not typeid in self.typeid_cache: # # This strips typedefs for pointers. We don't want that. # typeobj.nativeType = nativeType.GetUnqualifiedType() - tdata = self.TypeData(self, typeId) - tdata.name = typeName - tdata.lbitsize = nativeType.GetByteSize() * 8 + self.type_name_cache[typeid] = type_name + self.type_size_cache[typeid] = nativeType.GetByteSize() + type_code = None if code == lldb.eTypeClassBuiltin: - if utils.isFloatingPointTypeName(typeName): - tdata.code = TypeCode.Float - elif utils.isIntegralTypeName(typeName): - tdata.code = TypeCode.Integral - elif typeName in ('__int128', 'unsigned __int128'): - tdata.code = TypeCode.Integral - elif typeName == 'void': - tdata.code = TypeCode.Void - elif typeName == 'wchar_t': - tdata.code = TypeCode.Integral - elif typeName in ("char16_t", "char32_t", "char8_t"): - tdata.code = TypeCode.Integral + if utils.isFloatingPointTypeName(type_name): + type_code = TypeCode.Float + elif utils.isIntegralTypeName(type_name): + type_code = TypeCode.Integral + elif type_name in ('__int128', 'unsigned __int128'): + type_code = TypeCode.Integral + elif type_name == 'void': + type_code = TypeCode.Void + elif type_name == 'wchar_t': + type_code = TypeCode.Integral + elif type_name in ("char16_t", "char32_t", "char8_t"): + type_code = TypeCode.Integral else: - self.warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code)) + self.warn('UNKNOWN TYPE KEY: %s: %s' % (type_name, code)) elif code == lldb.eTypeClassEnumeration: - tdata.code = TypeCode.Enum - tdata.enumDisplay = lambda intval, addr, form: \ + type_code = TypeCode.Enum + self.type_enum_display_cache[typeid] = lambda intval, addr, form: \ self.nativeTypeEnumDisplay(nativeType, intval, form) elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat): - tdata.code = TypeCode.Complex + type_code = TypeCode.Complex elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion): - tdata.code = TypeCode.Struct - tdata.lalignment = lambda: \ - self.nativeStructAlignment(nativeType) - tdata.lfields = lambda value: \ - self.listMembers(value, nativeType) - tdata.templateArguments = lambda: \ - self.listTemplateParametersHelper(nativeType) + type_code = TypeCode.Struct elif code == lldb.eTypeClassFunction: - tdata.code = TypeCode.Function + type_code = TypeCode.Function elif code == lldb.eTypeClassMemberPointer: - tdata.code = TypeCode.MemberPointer - # warn('CREATE TYPE: %s' % typeId) + type_code = TypeCode.MemberPointer + + if code is not None: + self.type_code_cache[typeid] = type_code + + self.type_nativetype_cache[typeid] = nativeType + self.typeid_from_typekey[typeid_str] = typeid + + # self.warn('REUSE TYPE: %s' % typeid) + return typeid + + def nativeTemplateParameter(self, typeid, index, nativeType): + #n = nativeType.GetNumberOfTemplateArguments() + #if n != len(stringArgs): + # # Something wrong in the debug info. + # # Should work in theory, doesn't work in practice. + # # Items like std::allocator<std::pair<unsigned int const, float> report 0 + # # for nativeType.GetNumberOfTemplateArguments() with LLDB 3.8 + # return stringArgs + + kind = nativeType.GetTemplateArgumentKind(index) + # eTemplateArgumentKindNull = 0, + # eTemplateArgumentKindType, + # eTemplateArgumentKindDeclaration, + # eTemplateArgumentKindIntegral, + # eTemplateArgumentKindTemplate, + # eTemplateArgumentKindTemplateExpansion, + # eTemplateArgumentKindExpression, + # eTemplateArgumentKindPack + if kind == lldb.eTemplateArgumentKindType: + innerType = nativeType.GetTemplateArgumentType(index) \ + .GetUnqualifiedType().GetCanonicalType() + return self.Type(self, self.from_native_type(innerType)) + #elif kind == lldb.eTemplateArgumentKindIntegral: + # innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType() + # #DumperBase.warn('INNER TYP: %s' % innerType) + # basicType = innerType.GetBasicType() + # #DumperBase.warn('IBASIC TYP: %s' % basicType) + # inner = self.extractTemplateArgument(nativeType.GetName(), i) + # exp = '(%s)%s' % (innerType.GetName(), inner) + # #DumperBase.warn('EXP : %s' % exp) + # val = self.nativeParseAndEvaluate('(%s)%s' % (innerType.GetName(), inner)) + # # Clang writes 'int' and '0xfffffff' into the debug info + # # LLDB manages to read a value of 0xfffffff... + # #if basicType == lldb.eBasicTypeInt: + # value = val.GetValueAsUnsigned() + # if value >= 0x8000000: + # value -= 0x100000000 + # #DumperBase.warn('KIND: %s' % kind) + # targs.append(value) #else: - # warn('REUSE TYPE: %s' % typeId) - return self.Type(self, typeId) - - def listTemplateParametersHelper(self, nativeType): - stringArgs = self.listTemplateParameters(nativeType.GetName()) - n = nativeType.GetNumberOfTemplateArguments() - if n != len(stringArgs): - # Something wrong in the debug info. - # Should work in theory, doesn't work in practice. - # Items like std::allocator<std::pair<unsigned int const, float> report 0 - # for nativeType.GetNumberOfTemplateArguments() with LLDB 3.8 - return stringArgs - - targs = [] - for i in range(nativeType.GetNumberOfTemplateArguments()): - kind = nativeType.GetTemplateArgumentKind(i) - # eTemplateArgumentKindNull = 0, - # eTemplateArgumentKindType, - # eTemplateArgumentKindDeclaration, - # eTemplateArgumentKindIntegral, - # eTemplateArgumentKindTemplate, - # eTemplateArgumentKindTemplateExpansion, - # eTemplateArgumentKindExpression, - # eTemplateArgumentKindPack - if kind == lldb.eTemplateArgumentKindType: - innerType = nativeType.GetTemplateArgumentType( - i).GetUnqualifiedType().GetCanonicalType() - targs.append(self.fromNativeType(innerType)) - #elif kind == lldb.eTemplateArgumentKindIntegral: - # innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType() - # #DumperBase.warn('INNER TYP: %s' % innerType) - # basicType = innerType.GetBasicType() - # #DumperBase.warn('IBASIC TYP: %s' % basicType) - # inner = self.extractTemplateArgument(nativeType.GetName(), i) - # exp = '(%s)%s' % (innerType.GetName(), inner) - # #DumperBase.warn('EXP : %s' % exp) - # val = self.nativeParseAndEvaluate('(%s)%s' % (innerType.GetName(), inner)) - # # Clang writes 'int' and '0xfffffff' into the debug info - # # LLDB manages to read a value of 0xfffffff... - # #if basicType == lldb.eBasicTypeInt: - # value = val.GetValueAsUnsigned() - # if value >= 0x8000000: - # value -= 0x100000000 - # #DumperBase.warn('KIND: %s' % kind) - # targs.append(value) - else: - #DumperBase.warn('UNHANDLED TEMPLATE TYPE : %s' % kind) - targs.append(stringArgs[i]) # Best we can do. + # #DumperBase.warn('UNHANDLED TEMPLATE TYPE : %s' % kind) + # targs.append(stringArgs[i]) # Best we can do. #DumperBase.warn('TARGS: %s %s' % (nativeType.GetName(), [str(x) for x in targs])) - return targs - - def typeName(self, nativeType): - # Don't use GetDisplayTypeName since LLDB removed the inline namespace __1 - # https://reviews.llvm.org/D74478 - return nativeType.GetName() + #return targs + return None - def nativeTypeId(self, nativeType): - if nativeType and (nativeType.GetTypeClass() == lldb.eTypeClassTypedef): + def native_type_key(self, nativeType): + code = nativeType.GetTypeClass() + if nativeType and code == lldb.eTypeClassTypedef: nativeTargetType = nativeType.GetUnqualifiedType() if hasattr(nativeTargetType, 'GetCanonicalType'): nativeTargetType = nativeTargetType.GetCanonicalType() return '%s{%s}' % (nativeType.name, nativeTargetType.name) - name = self.typeName(nativeType) + # Don't use GetDisplayTypeName since LLDB removed the inline namespace __1 + # https://reviews.llvm.org/D74478 + name = nativeType.GetName() if name is None or len(name) == 0: c = '0' - elif name == '(anonymous struct)' and nativeType.GetTypeClass() == lldb.eTypeClassStruct: - c = 's' - elif name == '(anonymous struct)' and nativeType.GetTypeClass() == lldb.eTypeClassUnion: - c = 'u' + elif name == '(anonymous struct)': + c = 's' if code == lldb.eTypeClassStruct else 'u' else: return name fields = nativeType.get_fields_array() - typeId = c + ''.join(['{%s:%s}' % (f.name, self.nativeTypeId(f.GetType())) for f in fields]) - #DumperBase.warn('NATIVE TYPE ID FOR %s IS %s' % (name, typeId)) - return typeId + id_str = c + ''.join(['{%s:%s}' % + (f.name, self.typeid_for_string(self.native_type_key(f.GetType()))) + for f in fields]) + return id_str def nativeTypeEnumDisplay(self, nativeType, intval, form): if hasattr(nativeType, 'get_enum_members_array'): @@ -575,12 +569,82 @@ class Dumper(DumperBase): return '(' + ' | '.join(flags) + ') (' + (form % intval) + ')' return form % intval - def nativeDynamicTypeName(self, address, baseType): - return None # FIXME: Seems sufficient, no idea why. - addr = self.target.ResolveLoadAddress(address) - ctx = self.target.ResolveSymbolContextForAddress(addr, 0) - sym = ctx.GetSymbol() - return sym.GetName() + def nativeDynamicType(self, address, base_typeid): + return self.nativeDynamicType_2(address, base_typeid) + + def nativeDynamicType_1(self, address, base_typeid): + # Solutions 1: Breaks StdUniquePtr and QVariant1 test + return base_typeid + + def nativeDynamicType_2(self, address, base_typeid): + # Solution 2: ~10% slower in total than Solution 1 + typename = self.type_name(base_typeid) + #self.warn("LOOKING FOR DYN TYPE: 0x%x %s" % (address, typename)) + #self.warn(" PRETTY: 0x%x %s" % (address, self.prettySymbolByAddress(address))) + + expr = '(void*)%s' % address + value = self.target.EvaluateExpression(expr) + + #self.warn("VALUE: %s" % value) + if value.GetType().GetName() == "void *": + #self.warn("NO DYN TYPE: %s" % value) + return base_typeid + + dvalue = value.Dereference() + #self.warn("DVALUE: %s" % value) + sbtype = dvalue.GetType() + #self.warn("TYPE: %s" % sbtype) + + #self.warn("OUTPUT: %s" % output) + #self.warn("DYNTYPE: %s" % dyn_typename) + return self.from_native_type(sbtype) + + def nativeDynamicType_3(self, address, base_typeid): + # Solution 3: Doesn't improve over 1 + typename = self.type_name(base_typeid) + self.warn("LOOKING FOR DYN TYPE: 0x%x %s" % (address, typename)) + #self.warn(" PRETTY: 0x%x %s" % (address, self.prettySymbolByAddress(address))) + nativeType = self.type_nativetype_cache.get(base_typeid, None) + #self.warn(" NATIVE BASE %s" % nativeType) + if nativeType is None: + return base_typeid + #versionValue = self.target.EvaluateExpression('qtHookData[2]').GetNonSyntheticValue() + addr = lldb.SBAddress(address, self.target) + value = self.target.CreateValueFromAddress('x', addr, nativeType) + self.warn(" VALUE %s" % value) + return base_typeid + + def nativeDynamicType_4(self, address, base_typeid): + #self.warn("RESULT: %s" % result) + #self.warn("ADDRESS: 0x%x" % address) + + #thread = self.currentThread() + #frame = thread.GetFrameAtIndex(0) + #expr = '(void*)%s' % address + #value = self.target.EvaluateExpression(expr) + #sbtype = self.lookupNativeType(typename) + #addr = self.target.ResolveLoadAddress(address) + #addr = lldb.SBAddress(address, self.target) + #value = self.target.CreateValueFromAddress('x', addr, sbtype) + #x = lldb::DynamicValueType() + #lldb.eNoDynamicValues + #lldb.eDynamicCanRunTarget + #lldb.eDynamicDontRunTarget + #dyn_value = value.GetDynamicValue(lldb.eDynamicDontRunTarget) + #typ = dyn_value.GetType() + self.warn("GOT DYN VALUE: %s" % dyn_value) + #self.warn("GOT TYPE: %s FOR OBJECT AT 0x%x" % (typ, address)) + return self.from_native_type(typ) + + #result = lldb.SBCommandReturnObject() + #cmd = 'p (void*)%s' % address + #self.debugger.GetCommandInterpreter().HandleCommand(cmd, result) + #if not result.Succeeded(): + # return self.Type(self, typeid) + #output = result.GetOutput().strip() + #dyn_typename = output[1:output.find('$') - 4] + #sbtype = self.lookupNativeType(dyn_typename) + def stateName(self, s): try: @@ -638,11 +702,11 @@ class Dumper(DumperBase): #DumperBase.warn(' -> %s' % result) return self.fromNativeValue(result) - def pokeValue(self, typeName, *args): + def pokeValue(self, type_name, *args): thread = self.currentThread() frame = thread.GetFrameAtIndex(0) inner = ','.join(args) - value = frame.EvaluateExpression(typeName + '{' + inner + '}') + value = frame.EvaluateExpression(type_name + '{' + inner + '}') #DumperBase.warn(' TYPE: %s' % value.type) #DumperBase.warn(' ADDR: 0x%x' % value.address) #DumperBase.warn(' VALUE: %s' % value) @@ -830,8 +894,6 @@ class Dumper(DumperBase): #DumperBase.warn('RECURSE PTR') typeobj = self.lookupNativeType(name[:-1].strip()) if typeobj is not None: - #DumperBase.warn('RECURSE RESULT X: %s' % typeobj) - self.fromNativeType(typeobj.GetPointerType()) #DumperBase.warn('RECURSE RESULT: %s' % typeobj.GetPointerType()) return typeobj.GetPointerType() @@ -1289,14 +1351,12 @@ class Dumper(DumperBase): def findSymbol(self, symbolName): return self.target.FindFirstGlobalVariable(symbolName) - def warn(self, msg): - self.put('{name="%s",value="",type="",numchild="0"},' % toCString(msg)) - def fetchVariables(self, args): - (ok, res) = self.tryFetchInterpreterVariables(args) - if ok: - self.reportResult(res, args) - return + start_time = time.perf_counter() + #(ok, res) = self.tryFetchInterpreterVariables(args) + #if ok: + # self.reportResult(res, args) + # return self.setVariableFetchingOptions(args) @@ -1360,13 +1420,15 @@ class Dumper(DumperBase): # This can happen for unnamed function parameters with # default values: void foo(int = 0) continue - value = self.fromNativeFrameValue(val) + value = self.fromNativeValue(val) variables.append(value) self.handleLocals(variables) self.handleWatches(args) - self.put('],partial="%d"' % isPartial) + run_time = time.perf_counter() - start_time + + self.put('],partial="%d",runtime="%s"' % (isPartial, run_time)) self.reportResult(self.takeOutput(), args) @@ -1987,14 +2049,14 @@ class Dumper(DumperBase): value = self.hexdecode(args['value']) simpleType = int(args['simpleType']) lhs = self.findValueByExpression(expr) - typeName = lhs.GetType().GetName() - typeName = typeName.replace('::', '__') - pos = typeName.find('<') + type_name = lhs.GetType().GetName() + type_name = type_name.replace('::', '__') + pos = type_name.find('<') if pos != -1: - typeName = typeName[0:pos] - if typeName in self.qqEditable and not simpleType: + type_name = type_name[0:pos] + if type_name in self.qqEditable and not simpleType: expr = self.parseAndEvaluate(expr) - self.qqEditable[typeName](self, expr, value) + self.qqEditable[type_name](self, expr, value) else: self.parseAndEvaluate(expr + '=' + value) self.reportResult(self.describeError(error), args) @@ -2098,10 +2160,10 @@ class Tester(Dumper): if 'QT_CREATOR_LLDB_PROCESS' in os.environ: # Initialize Qt Creator dumper - try: + #try: theDumper = Dumper() - except Exception as error: - print('@\nstate="enginesetupfailed",error="{}"@\n'.format(error)) + #except Exception as error: + # print('@\nstate="enginesetupfailed",error="{}"@\n'.format(error)) # ------------------------------ For use in LLDB ------------------------------ |