import lldb class CrystalArraySyntheticProvider: def __init__(self, valobj, internal_dict): self.valobj = valobj self.buffer = None self.size = 0 def update(self): if self.valobj.type.is_pointer: self.valobj = self.valobj.Dereference() self.size = int(self.valobj.child[0].value) self.type = self.valobj.type self.buffer = self.valobj.child[3] def num_children(self): size = 0 if self.size is None else self.size return size def get_child_index(self, name): try: return int(name.lstrip('[').rstrip(']')) except: return -1 def get_child_at_index(self,index): if index >= self.size: return None try: elementType = self.buffer.type.GetPointeeType() offset = elementType.size * index return self.buffer.CreateChildAtOffset('[' + str(index) + ']', offset, elementType) except Exception as e: print('Got exception %s' % (str(e))) return None def findType(name, module): cachedTypes = module.GetTypes() for idx in range(cachedTypes.GetSize()): type = cachedTypes.GetTypeAtIndex(idx) if type.name == name: return type return None def CrystalString_SummaryProvider(value, dict): error = lldb.SBError() if value.TypeIsPointerType(): value = value.Dereference() process = value.GetTarget().GetProcess() byteSize = int(value.child[0].value) len = int(value.child[1].value) len = byteSize or len strAddr = value.child[2].load_addr val = process.ReadCStringFromMemory(strAddr, len + 1, error) return '"%s"' % val def __lldb_init_module(debugger, dict): debugger.HandleCommand(r'type synthetic add -l crystal_formatters.CrystalArraySyntheticProvider -x "^Array\(.+\)(\s*\**)?" -w Crystal') debugger.HandleCommand(r'type summary add -F crystal_formatters.CrystalString_SummaryProvider -x "^(String|\(String \| Nil\))(\s*\**)?$" -w Crystal') debugger.HandleCommand(r'type category enable Crystal')