aboutsummaryrefslogtreecommitdiffstats
path: root/share/qtcreator/debugger/lldbbridge.py
diff options
context:
space:
mode:
Diffstat (limited to 'share/qtcreator/debugger/lldbbridge.py')
-rw-r--r--share/qtcreator/debugger/lldbbridge.py606
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 ------------------------------