""" This python script provides LLDB formatters for Slang core types. To use it, add the following line to your ~/.lldbinit file: command script import /path/to/source/core/core_lldb.py """ import lldb # Set to True to enable the logger ENABLE_LOGGING = True # log to the LLDB formatter stream def log(msg): if ENABLE_LOGGING: lldb.formatters.Logger.Logger() >> msg def make_string(F: lldb.SBData, L: int) -> str: strval = "" G = F.uint8 for X in range(L): V = G[X] if V == 0: break strval = strval + chr(V % 256) return '"' + strval + '"' # Return the pointer to the data in a Slang::RefPtr def get_ref_pointer(valobj: lldb.SBValue) -> lldb.SBValue: return valobj.GetNonSyntheticValue().GetChildMemberWithName("pointer") # Check if a pointer is nullptr def is_nullptr(valobj: lldb.SBValue) -> bool: return valobj.GetValueAsUnsigned(0) == 0 # Slang::String summary def String_summary(valobj: lldb.SBValue, dict) -> str: buffer_ptr = get_ref_pointer(valobj.GetChildMemberWithName("m_buffer")) if is_nullptr(buffer_ptr): return '""' buffer = buffer_ptr.Dereference() length = buffer.GetChildMemberWithName("length").GetValueAsUnsigned(0) data = buffer_ptr.GetPointeeData(1, length) return make_string(data, length) # Slang::UnownedStringSlice summary def UnownedStringSlice_summary(valobj: lldb.SBValue, dict) -> str: begin = valobj.GetChildMemberWithName("m_begin") end = valobj.GetChildMemberWithName("m_end") length = end.GetValueAsUnsigned(0) - begin.GetValueAsUnsigned(0) if length <= 0: return '""' data = begin.GetPointeeData(0, length) return make_string(data, length) # Slang::RefPtr synthetic provider class RefPtr_synthetic(lldb.SBSyntheticValueProvider): def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): return True def num_children(self): return len(self.children) def get_child_index(self, name): for idx in range(self.num_children()): if self.children[idx].GetName() == name: return idx return -1 def get_child_at_index(self, idx): if idx >= 0 and idx < self.num_children(): return self.children[idx] else: return None def update(self): self.pointer = self.valobj.GetNonSyntheticValue().GetChildMemberWithName( "pointer" ) self.children = [] if not is_nullptr(self.pointer): self.children = self.pointer.Dereference().children # Slang::RefPtr summary def RefPtr_summary(valobj: lldb.SBValue, dict) -> str: pointer = valobj.GetNonSyntheticValue().GetChildMemberWithName("pointer") if is_nullptr(pointer): return "nullptr" pointee = pointer.Dereference() refcount = pointee.GetChildMemberWithName("referenceCount").GetValueAsUnsigned() return str(pointer.GetValue()) + " refcount=" + str(refcount) # Slang::ComPtr synthetic provider class ComPtr_synthetic(lldb.SBSyntheticValueProvider): def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): return len(self.children) > 0 def num_children(self): return len(self.children) def get_child_index(self, name): for idx in range(self.num_children()): if self.children[idx].GetName() == name: return idx return -1 def get_child_at_index(self, idx): if idx >= 0 and idx < self.num_children(): return self.children[idx] else: return None def update(self): self.pointer = self.valobj.GetChildMemberWithName("m_ptr") self.children = [] if not is_nullptr(self.pointer): self.children = self.pointer.Dereference().children # Slang::ComPtr summary def ComPtr_summary(valobj: lldb.SBValue, dict) -> str: pointer = valobj.GetNonSyntheticValue().GetChildMemberWithName("m_ptr") if is_nullptr(pointer): return "nullptr" return str(pointer.GetValue()) # Slang::Array synthetic provider class Array_synthetic(lldb.SBSyntheticValueProvider): def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): return True def num_children(self): return self.count.GetValueAsUnsigned(0) def get_child_index(self, name): return int(name.lstrip("[").rstrip("]")) def get_child_at_index(self, idx): if idx >= 0 and idx < self.num_children(): offset = idx * self.data_size return self.buffer.CreateChildAtOffset( "[" + str(idx) + "]", offset, self.data_type ) else: return None def update(self): self.count = self.valobj.GetChildMemberWithName("m_count") self.buffer = self.valobj.GetChildMemberWithName("m_buffer") self.data_type = self.buffer.GetType().GetArrayElementType() self.data_size = self.data_type.GetByteSize() # Slang::List synthetic provider class List_synthetic(lldb.SBSyntheticValueProvider): def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): return True def num_children(self): return self.count.GetValueAsUnsigned(0) def get_child_index(self, name): return int(name.lstrip("[").rstrip("]")) def get_child_at_index(self, idx): if idx >= 0 and idx < self.num_children(): offset = idx * self.data_size return self.buffer.CreateChildAtOffset( "[" + str(idx) + "]", offset, self.data_type ) else: return None def update(self): self.count = self.valobj.GetChildMemberWithName("m_count") self.buffer = self.valobj.GetChildMemberWithName("m_buffer") self.data_type = self.buffer.GetType().GetPointeeType() self.data_size = self.data_type.GetByteSize() # Slang::ShortList synthetic provider class ShortList_synthetic(lldb.SBSyntheticValueProvider): def __init__(self, valobj: lldb.SBValue, dict): self.valobj = valobj def has_children(self): return True def num_children(self): return self.count.GetValueAsUnsigned(0) def get_child_index(self, name): return int(name.lstrip("[").rstrip("]")) def get_child_at_index(self, idx): if idx >= 0 and idx < self.short_count: offset = idx * self.data_size return self.short_buffer.CreateChildAtOffset( "[" + str(idx) + "]", offset, self.data_type ) elif idx >= self.short_count and idx < self.num_children(): offset = (idx - self.short_count) * self.data_size return self.buffer.CreateChildAtOffset( "[" + str(idx) + "]", offset, self.data_type ) else: return None def update(self): self.count = self.valobj.GetChildMemberWithName("m_count") self.buffer = self.valobj.GetChildMemberWithName("m_buffer") self.short_buffer = self.valobj.GetChildMemberWithName("m_shortBuffer") self.short_count = self.short_buffer.GetNumChildren() self.data_type = self.buffer.GetType().GetPointeeType() self.data_size = self.data_type.GetByteSize() def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict): if ENABLE_LOGGING: lldb.formatters.Logger._lldb_formatters_debug_level = 2 commands = [ # Slang::String "type summary add Slang::String -F core_lldb.String_summary -w slang", # Slang::UnownedStringSlice "type summary add Slang::UnownedStringSlice -F core_lldb.UnownedStringSlice_summary -w slang", # Slang::RefPtr 'type synthetic add -x "^Slang::RefPtr<.+>$" -l core_lldb.RefPtr_synthetic -w slang', 'type summary add -x "^Slang::RefPtr<.+>$" -F core_lldb.RefPtr_summary -w slang', # Slang::ComPtr 'type synthetic add -x "^Slang::ComPtr<.+>$" -l core_lldb.ComPtr_synthetic -w slang', 'type summary add -x "^Slang::ComPtr<.+>$" -F core_lldb.ComPtr_summary -w slang', # Slang::Array 'type synthetic add -x "^Slang::Array<.+>$" -l core_lldb.Array_synthetic -w slang', 'type summary add --x "^Slang::Array<.+>$" --summary-string "size=${svar%#}" -w slang', # Slang::List 'type synthetic add -x "^Slang::List<.+>$" -l core_lldb.List_synthetic -w slang', 'type summary add --expand -x "^Slang::List<.+>$" --summary-string "size=${var.m_count} capacity=${var.m_capacity}" -w slang', # Slang::ShortList 'type synthetic add -x "^Slang::ShortList<.+>$" -l core_lldb.ShortList_synthetic -w slang', 'type summary add --expand -x "^Slang::ShortList<.+>$" --summary-string "size=${var.m_count} capacity=${var.m_capacity}" -w slang', # Enable slang category "type category enable slang", ] for c in commands: debugger.HandleCommand(c)