summary refs log tree commit diff stats
path: root/tools
diff options
context:
space:
mode:
authorJoey <jyapayne@pm.me>2023-03-18 23:28:00 -0600
committerGitHub <noreply@github.com>2023-03-19 06:28:00 +0100
commitcae539996a9a3b4c79af06d9ba8a0f9273bab3e1 (patch)
tree6cf00478b80f344540499392bd7e9b5f96cdc2b4 /tools
parenta9d0124b5d6e75df708497fc288d602bb2585369 (diff)
downloadNim-cae539996a9a3b4c79af06d9ba8a0f9273bab3e1.tar.gz
Update LLDB debug script + Add Custom Nim formatters (#21517)
* Fix custom objects, fix handling of nil variables

* Rename because lldb complains about dashes in filename

* Add example of how to use custom type formatting from Nim

* Add synthetic objects with dynamic fields and add an example
Diffstat (limited to 'tools')
-rw-r--r--tools/debug/customdebugtype.nim72
-rw-r--r--tools/debug/nimlldb.py (renamed from tools/debug/nim-lldb.py)1041
2 files changed, 763 insertions, 350 deletions
diff --git a/tools/debug/customdebugtype.nim b/tools/debug/customdebugtype.nim
new file mode 100644
index 000000000..f48979661
--- /dev/null
+++ b/tools/debug/customdebugtype.nim
@@ -0,0 +1,72 @@
+## This is a demo file containing an example of how to
+## create custom LLDB summaries and objects with synthetic
+## children. These are implemented in Nim and called from the Python
+## nimlldb.py module.
+##
+## For summaries, prefix your proc names with "lldbDebugSummary", use
+## the `{.exportc.}` pragma, and return a string. Also, any `$` proc
+## that is available will be used for a given type.
+##
+## For creating a synthetic object (LLDB will display the children), use
+## the prefix "lldbDebugSynthetic", use the `{.exportc.}` pragma, and
+## return any Nim object, array, or sequence. Returning a Nim object
+## will display the fields and values of the object as children.
+## Returning an array or sequence will display children with the index
+## surrounded by square brackets as the key name
+##
+## You may also return a Nim table that contains the string
+## "LLDBDynamicObject" (case insensitive). This allows for dynamic
+## fields to be created at runtime instead of at compile time if you
+## return a Nim object as mentioned above. See the proc
+## `lldbDebugSyntheticDynamicFields` below for an example
+
+import intsets
+import tables
+
+type
+  CustomType* = object of RootObj # RootObj is not necessary, but can be used
+    myField*: int
+
+  DynamicFields* = object
+    customField*: string
+
+  CustomSyntheticReturn* = object
+    differentField*: float
+
+  LLDBDynamicObject = object
+    fields: TableRef[string, int]
+
+  LLDBDynamicObjectDynamicFields = object
+    fields: TableRef[string, string]
+
+proc lldbDebugSummaryCustomType*(ty: CustomType): string {.exportc.} =
+  ## Will display "CustomType(myField: <int_val>)" as a summary
+  result = "CustomType" & $ty
+
+proc lldbDebugSyntheticCustomType*(ty: CustomType): CustomSyntheticReturn {.exportc.} =
+  ## Will display differentField: <float_val> as a child of CustomType instead of
+  ## myField: <int_val>
+  result = CustomSyntheticReturn(differentField: ty.myField.float)
+
+proc lldbDebugSyntheticDynamicFields*(ty: DynamicFields): LLDBDynamicObjectDynamicFields {.exportc.} =
+  ## Returning an object that contains "LLDBDynamicObject" in the type name will expect an
+  ## object with one property that is a Nim Table/TableRef. If the key is a string,
+  ## it will appear in the debugger like an object field name. The value will be whatever you
+  ## set it to here as well.
+  let fields = {"customFieldName": ty.customField & " MORE TEXT"}.newTable()
+  return LLDBDynamicObjectDynamicFields(fields: fields)
+
+proc lldbDebugSummaryIntSet*(intset: IntSet): string {.exportc.} =
+  ## This will print the object in the LLDB summary just as Nim prints it
+  result = $intset
+
+proc lldbDebugSyntheticIntSet*(intset: IntSet): seq[int] {.exportc.} =
+  ## This will create a synthetic object to make it so that IntSet
+  ## will appear as a Nim object in the LLDB debugger window
+  ##
+  ## returning a seq here will display children like:
+  ## [0]: <child_value>
+  ##
+  result = newSeqOfCap[int](intset.len)
+  for val in intset:
+    result.add(val)
diff --git a/tools/debug/nim-lldb.py b/tools/debug/nimlldb.py
index 625b75988..4bc4e771f 100644
--- a/tools/debug/nim-lldb.py
+++ b/tools/debug/nimlldb.py
@@ -13,70 +13,87 @@ def sbvaluegetitem(self: lldb.SBValue, name: Union[int, str]) -> lldb.SBValue:
 # Make this easier to work with
 lldb.SBValue.__getitem__ = sbvaluegetitem
 
+NIM_IS_V2 = True
 
-def colored(in_str, *args, **kwargs):
-    # TODO: Output in color if user is in terminal
-    return in_str
 
-
-def reprEnum(val, typ):
-    """
-    this is a port of the nim runtime function `reprEnum` to python
-    NOTE: DOES NOT WORK WITH ORC
-    """
-    val = int(val)
-    n = typ["node"]
-    sons_type = n["sons"].type.GetPointeeType().GetPointeeType()
-    sons = n["sons"].deref.Cast(sons_type.GetPointerType().GetArrayType(3))
-    flags = int(typ["flags"].unsigned)
-    # 1 << 6 is {ntfEnumHole}
-    if ((1 << 6) & flags) == 0:
-        offset = val - sons[0]["offset"].unsigned
-        if offset >= 0 and 0 < n["len"].unsigned:
-            return NCSTRING(sons[offset]["name"])[1:-1]
-    else:
-        # ugh we need a slow linear search:
-        for i in range(n["len"].unsigned):
-            if sons[i]["offset"].unsigned == val:
-                return NCSTRING(sons[i]["name"])[1:-1]
-
-    return str(val) + " (invalid data!)"
-
-
-def get_nti(value, nim_name=None):
-    """DOES NOT WORK WITH ORC"""
+def get_nti(value: lldb.SBValue, nim_name=None):
     name_split = value.type.name.split("_")
     type_nim_name = nim_name or name_split[1]
     id_string = name_split[-1].split(" ")[0]
 
     type_info_name = "NTI" + type_nim_name.lower() + "__" + id_string + "_"
-    print("TYPEINFONAME: ", type_info_name)
     nti = value.target.FindFirstGlobalVariable(type_info_name)
-    if nti is None:
+    if not nti.IsValid():
         type_info_name = "NTI" + "__" + id_string + "_"
         nti = value.target.FindFirstGlobalVariable(type_info_name)
-    if nti is None:
-        print(
-            f"NimEnumPrinter: lookup global symbol: '{type_info_name}' failed for {value.type.name}.\n"
-        )
+    if not nti.IsValid():
+        print(f"NimEnumPrinter: lookup global symbol: '{type_info_name}' failed for {value.type.name}.\n")
     return type_nim_name, nti
 
 
-def enum_to_string(value):
-    type_nim_name, nti = get_nti(value)
-    if nti is None:
-        return type_nim_name + "(" + str(value.unsigned) + ")"
-    return reprEnum(value.signed, nti), nti
+def enum_to_string(value: lldb.SBValue, int_val=None, nim_name=None):
+    tname = nim_name or value.type.name.split("_")[1]
+
+    enum_val = value.signed
+    if int_val is not None:
+        enum_val = int_val
+
+    default_val = f"{tname}.{str(enum_val)}"
+
+    fn_syms = value.target.FindFunctions("reprEnum")
+    if not fn_syms.GetSize() > 0:
+        return default_val
+
+    fn_sym: lldb.SBSymbolContext = fn_syms.GetContextAtIndex(0)
+
+    fn: lldb.SBFunction = fn_sym.function
 
+    fn_type: lldb.SBType = fn.type
+    arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
+    if arg_types.GetSize() < 2:
+        return default_val
 
-def to_string(value):
+    arg1_type: lldb.SBType = arg_types.GetTypeAtIndex(0)
+    arg2_type: lldb.SBType = arg_types.GetTypeAtIndex(1)
+
+    ty_info_name, nti = get_nti(value, nim_name=tname)
+
+    if not nti.IsValid():
+        return default_val
+
+    call = f"{fn.name}(({arg1_type.name}){enum_val}, ({arg2_type.name})" + str(nti.GetLoadAddress()) + ");"
+
+    res = executeCommand(call)
+
+    if res.error.fail:
+        return default_val
+
+    return f"{tname}.{res.summary[1:-1]}"
+
+
+def to_string(value: lldb.SBValue):
     # For getting NimStringDesc * value
+    value = value.GetNonSyntheticValue()
+
+    # Check if data pointer is Null
+    if value.type.is_pointer and value.unsigned == 0:
+        return None
+
+    size = int(value["Sup"]["len"].unsigned)
+
+    if size == 0:
+        return ""
+
+    if size > 2**14:
+        return "... (too long) ..."
+
     data = value["data"]
-    try:
-        size = int(value["Sup"]["len"].unsigned)
-        if size > 2**14:
-            return None
-    except TypeError:
+
+    # Check if first element is NULL
+    base_data_type = value.target.FindFirstType("char")
+    cast = data.Cast(base_data_type)
+
+    if cast.unsigned == 0:
         return None
 
     cast = data.Cast(value.target.FindFirstType("char").GetArrayType(size))
@@ -84,89 +101,117 @@ def to_string(value):
 
 
 def to_stringV2(value: lldb.SBValue):
-    # For getting NimStringDesc * value
+    # For getting NimStringV2 value
+    value = value.GetNonSyntheticValue()
+
     data = value["p"]["data"]
-    try:
-        size = int(value["len"].signed)
-        if size > 2**14:
-            return "... (too long)"
-    except TypeError:
+
+    # Check if data pointer is Null
+    if value["p"].unsigned == 0:
+        return None
+
+    size = int(value["len"].signed)
+
+    if size == 0:
         return ""
 
+    if size > 2**14:
+        return "... (too long) ..."
+
+    # Check if first element is NULL
     base_data_type = data.type.GetArrayElementType().GetTypedefedType()
+    cast = data.Cast(base_data_type)
+
+    if cast.unsigned == 0:
+        return None
+
     cast = data.Cast(base_data_type.GetArrayType(size))
     return bytearray(cast.data.uint8s).decode("utf-8")
 
 
-def NimStringDesc(value, internal_dict):
-    res = to_string(value)
-    if res:
-        return colored('"' + res + '"', "red")
-    else:
-        return str(value)
+def NimString(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
 
+    if NIM_IS_V2:
+        res = to_stringV2(value)
+    else:
+        res = to_string(value)
 
-def NimStringV2(value: lldb.SBValue, internal_dict):
-    res = to_stringV2(value.GetNonSyntheticValue())
     if res is not None:
-        return colored('"' + res + '"', "red")
+        return f'"{res}"'
     else:
-        return str(value)
-
+        return "nil"
 
-def NCSTRING(value: lldb.SBValue, internal_dict=None):
-    ty = value.Dereference().type
-    val = value.target.CreateValueFromAddress(
-        value.name or "temp", lldb.SBAddress(value.unsigned, value.target), ty
-    ).AddressOf()
-    return val.summary
 
+def rope_helper(value: lldb.SBValue) -> str:
+    value = value.GetNonSyntheticValue()
+    if value.type.is_pointer and value.unsigned == 0:
+        return ""
 
-def ObjectV1(value, internal_dict):
-    if not value.num_children and not value.value:
+    if value["length"].unsigned == 0:
         return ""
 
-    ignore_fields = set()
-    if "colonObjectType" in value.type.name:
-        value = value.Dereference()
-        ignore_fields.add("Sup")
+    if NIM_IS_V2:
+        str_val = to_stringV2(value["data"])
+    else:
+        str_val = to_string(value["data"])
 
-    if not value.type.name:
-        return ""
+    if str_val is None:
+        str_val = ""
+
+    return rope_helper(value["left"]) + str_val + rope_helper(value["right"])
 
-    summary = value.summary
-    if summary is not None:
-        return summary
 
-    if "_" in value.type.name:
-        obj_name = value.type.name.split("_")[1].replace("colonObjectType", "")
+def Rope(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    rope_str = rope_helper(value)
+
+    if len(rope_str) == 0:
+        rope_str = "nil"
     else:
-        obj_name = value.type.name
+        rope_str = f'"{rope_str}"'
 
-    obj_name = colored(obj_name, "green")
+    return f"Rope({rope_str})"
 
-    num_children = value.num_children
 
-    fields = ", ".join(
-        [
-            value[i].name
-            + ": "
-            + (value[i].summary or value[i].value or value[i].type.name or "not found")
-            for i in range(num_children)
-            if value[i].name not in ignore_fields
-        ]
-    )
-
-    res = f"{obj_name}({fields})"
-    return res
+def NCSTRING(value: lldb.SBValue, internal_dict=None):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    ty = value.Dereference().type
+    val = value.target.CreateValueFromAddress(
+        value.name or "temp", lldb.SBAddress(value.unsigned, value.target), ty
+    ).AddressOf()
+    return val.summary
 
 
 def ObjectV2(value: lldb.SBValue, internal_dict):
-    custom_summary = get_summary(value)
-    if not custom_summary is None:
-        return custom_summary
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
 
     orig_value = value.GetNonSyntheticValue()
+    if orig_value.type.is_pointer and orig_value.unsigned == 0:
+        return "nil"
+
+    custom_summary = get_custom_summary(value)
+    if custom_summary is not None:
+        return custom_summary
+
     while orig_value.type.is_pointer:
         orig_value = orig_value.Dereference()
 
@@ -186,39 +231,91 @@ def ObjectV2(value: lldb.SBValue, internal_dict):
 
 
 def Number(value: lldb.SBValue, internal_dict):
-    while value.type.is_pointer:
-        value = value.Dereference()
-    return colored(str(value.signed), "yellow")
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    if value.type.is_pointer and value.signed == 0:
+        return "nil"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    return str(value.signed)
 
 
 def Float(value: lldb.SBValue, internal_dict):
-    while value.type.is_pointer:
-        value = value.Dereference()
-    return colored(str(value.value), "yellow")
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    return str(value.value)
 
 
 def UnsignedNumber(value: lldb.SBValue, internal_dict):
-    while value.type.is_pointer:
-        value = value.Dereference()
-    return colored(str(value.unsigned), "yellow")
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    return str(value.unsigned)
 
 
 def Bool(value: lldb.SBValue, internal_dict):
-    while value.type.is_pointer:
-        value = value.Dereference()
-    return colored(str(value.GetValue()), "red")
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    return str(value.value)
 
 
 def CharArray(value: lldb.SBValue, internal_dict):
-    return str([colored(f"'{char}'", "red") for char in value.uint8s])
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    return str([f"'{char}'" for char in value.uint8s])
 
 
 def Array(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    value = value.GetNonSyntheticValue()
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
     value = value.GetNonSyntheticValue()
     return "[" + ", ".join([value[i].summary for i in range(value.num_children)]) + "]"
 
 
 def Tuple(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
     while value.type.is_pointer:
         value = value.Dereference()
 
@@ -237,30 +334,67 @@ def Tuple(value: lldb.SBValue, internal_dict):
     return "(" + ", ".join(fields) + f")"
 
 
-def Enum(value, internal_dict):
-    tname = value.type.name.split("_")[1]
-    return colored(f"{tname}." + str(value.signed), "blue")
+def is_local(value: lldb.SBValue) -> bool:
+    line: lldb.SBLineEntry = value.frame.GetLineEntry()
+    decl: lldb.SBDeclaration = value.GetDeclaration()
+
+    if line.file == decl.file and decl.line != 0:
+        return True
+
+    return False
+
+
+def is_in_scope(value: lldb.SBValue) -> bool:
+    line: lldb.SBLineEntry = value.frame.GetLineEntry()
+    decl: lldb.SBDeclaration = value.GetDeclaration()
+
+    if is_local(value) and decl.line < line.line:
+        return True
+
+    return False
+
 
+def Enum(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
 
-def EnumSet(value, internal_dict):
-    type_nim_name = value.type.name.split("_")[2]
-    # type_nim_name, nti = get_nti(value, type_nim_name)
+    custom_summary = get_custom_value_summary(value)
+    if custom_summary is not None:
+        return custom_summary
+
+    return enum_to_string(value)
 
-    val = int(value.signed)
-    # if nti:
-    #     enum_strings = []
-    #     i = 0
-    #     while val > 0:
-    #         if (val & 1) == 1:
-    #             enum_strings.append(reprEnum(i, nti))
-    #         val = val >> 1
-    #         i += 1
 
-    #     return '{' + ', '.join(enum_strings) + '}'
-    return colored(f"{type_nim_name}." + str(val), "blue")
+def EnumSet(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
 
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
+
+    vals = []
+    max_vals = 7
+    for child in value.children:
+        vals.append(child.summary)
+        if len(vals) > max_vals:
+            vals.append("...")
+            break
+
+    return "{" + ", ".join(vals) + "}"
+
+
+def Set(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if custom_summary is not None:
+        return custom_summary
 
-def Set(value, internal_dict):
     vals = []
     max_vals = 7
     for child in value.children:
@@ -273,6 +407,14 @@ def Set(value, internal_dict):
 
 
 def Table(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if custom_summary is not None:
+        return custom_summary
+
     fields = []
 
     for i in range(value.num_children):
@@ -280,65 +422,66 @@ def Table(value: lldb.SBValue, internal_dict):
         val = value[i].summary
         fields.append(f"{key}: {val}")
 
-    table_suffix = "Table"
-    return "{" + ", ".join(fields) + f"}}.{table_suffix}"
+    return "Table({" + ", ".join(fields) + "})"
 
 
 def HashSet(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
+
+    custom_summary = get_custom_summary(value)
+    if custom_summary is not None:
+        return custom_summary
+
     fields = []
 
     for i in range(value.num_children):
         fields.append(f"{value[i].summary}")
 
-    table_suffix = "HashSet"
-
-    return "{" + ", ".join(fields) + f"}}.{table_suffix}"
+    return "HashSet({" + ", ".join(fields) + "})"
 
 
 def StringTable(value: lldb.SBValue, internal_dict):
-    table = value.GetNonSyntheticValue()
-    mode = table["mode"].unsigned
-
-    table_suffix = "StringTable"
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
 
-    table_mode = ""
-    if mode == 0:
-        table_mode = "Case Sensitive"
-    elif mode == 1:
-        table_mode = "Case Insensitive"
-    elif mode == 2:
-        table_mode = "Style Insensitive"
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
 
     fields = []
 
-    for i in range(value.num_children):
+    for i in range(value.num_children - 1):
         key = value[i].name
         val = value[i].summary
         fields.append(f"{key}: {val}")
 
-    return "{" + ", ".join(fields) + f"}}.{table_suffix}({table_mode})"
+    mode = value[value.num_children - 1].summary
 
+    return "StringTable({" + ", ".join(fields) + f"}}, mode={mode})"
 
-def Sequence(value: lldb.SBValue, internal_dict):
-    value = value.GetNonSyntheticValue()
 
-    data_len = int(value["len"].unsigned)
-    data = value["p"]["data"]
-    base_data_type = data.type.GetArrayElementType()
+def Sequence(value: lldb.SBValue, internal_dict):
+    if is_local(value):
+        if not is_in_scope(value):
+            return "undefined"
 
-    cast = data.Cast(base_data_type.GetArrayType(data_len))
+    custom_summary = get_custom_summary(value)
+    if not custom_summary is None:
+        return custom_summary
 
-    return (
-        "@["
-        + ", ".join([cast[i].summary or cast[i].type.name for i in range(data_len)])
-        + "]"
-    )
+    return "@[" + ", ".join([value[i].summary for i in range(value.num_children)]) + "]"
 
 
 class StringChildrenProvider:
     def __init__(self, value: lldb.SBValue, internalDict):
         self.value = value
         self.data_type: lldb.SBType
+        if not NIM_IS_V2:
+            self.data_type = self.value.target.FindFirstType("char")
+
         self.first_element: lldb.SBValue
         self.update()
         self.count = 0
@@ -351,18 +494,63 @@ class StringChildrenProvider:
 
     def get_child_at_index(self, index):
         offset = index * self.data_size
-        return self.first_element.CreateChildAtOffset(
-            "[" + str(index) + "]", offset, self.data_type
-        )
+        return self.first_element.CreateChildAtOffset("[" + str(index) + "]", offset, self.data_type)
+
+    def get_data(self) -> lldb.SBValue:
+        return self.value["p"]["data"] if NIM_IS_V2 else self.value["data"]
+
+    def get_len(self) -> int:
+        if NIM_IS_V2:
+            if self.value["p"].unsigned == 0:
+                return 0
+
+            size = int(self.value["len"].signed)
+
+            if size == 0:
+                return 0
+
+            data = self.value["p"]["data"]
+
+            # Check if first element is NULL
+            base_data_type = data.type.GetArrayElementType().GetTypedefedType()
+            cast = data.Cast(base_data_type)
+
+            if cast.unsigned == 0:
+                return 0
+        else:
+            if self.value.type.is_pointer and self.value.unsigned == 0:
+                return 0
+
+            size = int(self.value["Sup"]["len"].unsigned)
+
+            if size == 0:
+                return 0
+
+            data = self.value["data"]
+
+            # Check if first element is NULL
+            base_data_type = self.value.target.FindFirstType("char")
+            cast = data.Cast(base_data_type)
+
+            if cast.unsigned == 0:
+                return 0
+
+        return size
 
     def update(self):
-        data = self.value["p"]["data"]
-        size = int(self.value["len"].unsigned)
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+
+        data = self.get_data()
+        size = self.get_len()
 
         self.count = size
         self.first_element = data
 
-        self.data_type = data.type.GetArrayElementType().GetTypedefedType()
+        if NIM_IS_V2:
+            self.data_type = data.type.GetArrayElementType().GetTypedefedType()
+
         self.data_size = self.data_type.GetByteSize()
 
     def has_children(self):
@@ -377,16 +565,14 @@ class ArrayChildrenProvider:
         self.update()
 
     def num_children(self):
-        return self.value.num_children
+        return self.has_children() and self.value.num_children
 
     def get_child_index(self, name: str):
         return int(name.lstrip("[").rstrip("]"))
 
     def get_child_at_index(self, index):
         offset = index * self.value[index].GetByteSize()
-        return self.first_element.CreateChildAtOffset(
-            "[" + str(index) + "]", offset, self.data_type
-        )
+        return self.first_element.CreateChildAtOffset("[" + str(index) + "]", offset, self.data_type)
 
     def update(self):
         if not self.has_children():
@@ -396,7 +582,10 @@ class ArrayChildrenProvider:
         self.data_type = self.value.type.GetArrayElementType()
 
     def has_children(self):
-        return bool(self.num_children())
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return False
+        return bool(self.value.num_children)
 
 
 class SeqChildrenProvider:
@@ -405,25 +594,38 @@ class SeqChildrenProvider:
         self.data_type: lldb.SBType
         self.first_element: lldb.SBValue
         self.data: lldb.SBValue
+        self.count = 0
         self.update()
 
     def num_children(self):
-        return int(self.value["len"].unsigned)
+        return self.count
 
     def get_child_index(self, name: str):
         return int(name.lstrip("[").rstrip("]"))
 
     def get_child_at_index(self, index):
         offset = index * self.data[index].GetByteSize()
-        return self.first_element.CreateChildAtOffset(
-            "[" + str(index) + "]", offset, self.data_type
-        )
+        return self.first_element.CreateChildAtOffset("[" + str(index) + "]", offset, self.data_type)
+
+    def get_data(self) -> lldb.SBValue:
+        return self.value["p"]["data"] if NIM_IS_V2 else self.value["data"]
+
+    def get_len(self) -> lldb.SBValue:
+        return self.value["len"] if NIM_IS_V2 else self.value["Sup"]["len"]
 
     def update(self):
+        self.count = 0
+
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+
+        self.count = self.get_len().unsigned
+
         if not self.has_children():
             return
 
-        data = self.value["p"]["data"]
+        data = self.get_data()
         self.data_type = data.type.GetArrayElementType()
 
         self.data = data.Cast(self.data_type.GetArrayType(self.num_children()))
@@ -455,35 +657,29 @@ class ObjectChildrenProvider:
     def populate_children(self):
         self.children.clear()
         self.child_list = []
-        stack = [self.value]
+
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+
+        stack = [self.value.GetNonSyntheticValue()]
 
         index = 0
 
         while stack:
             cur_val = stack.pop()
+            if cur_val.type.is_pointer and cur_val.unsigned == 0:
+                continue
+
             while cur_val.type.is_pointer:
                 cur_val = cur_val.Dereference()
 
-            if cur_val.num_children > 0 and cur_val[0].name == "m_type":
-                if "_" in cur_val.type.name:
-                    tname = cur_val.type.name.split("_")[1].replace(
-                        "colonObjectType", ""
-                    )
-                else:
-                    tname = cur_val.type.name
-                if tname == "TNimTypeV2":
-                    # We've reached the end
-                    break
-
-            if (
-                cur_val.num_children > 0
-                and cur_val[0].name == "Sup"
-                and cur_val[0].type.name.startswith("tyObject")
-            ):
+            # Add super objects if they exist
+            if cur_val.num_children > 0 and cur_val[0].name == "Sup" and cur_val[0].type.name.startswith("tyObject"):
                 stack.append(cur_val[0])
 
-            for i in range(cur_val.num_children):
-                child = cur_val[i]
+            for child in cur_val.children:
+                child = child.GetNonSyntheticValue()
                 if child.name == "Sup":
                     continue
                 self.children[child.name] = index
@@ -512,12 +708,21 @@ class HashSetChildrenProvider:
     def get_child_at_index(self, index):
         return self.child_list[index]
 
+    def get_data(self) -> lldb.SBValue:
+        return self.value["data"]["p"]["data"] if NIM_IS_V2 else self.value["data"]["data"]
+
+    def get_len(self) -> lldb.SBValue:
+        return self.value["data"]["len"] if NIM_IS_V2 else self.value["data"]["Sup"]["len"]
+
     def update(self):
         self.child_list = []
-        data = self.value["data"]
 
-        tuple_len = int(data["len"].unsigned)
-        tuple = data["p"]["data"]
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+
+        tuple_len = int(self.get_len().unsigned)
+        tuple = self.get_data()
 
         base_data_type = tuple.type.GetArrayElementType()
 
@@ -526,13 +731,11 @@ class HashSetChildrenProvider:
         index = 0
         for i in range(tuple_len):
             el = cast[i]
-            field0 = int(el["Field0"].unsigned)
+            field0 = int(el[0].unsigned)
             if field0 == 0:
                 continue
-            key = el["Field1"]
-            child = key.CreateValueFromAddress(
-                f"[{str(index)}]", key.GetLoadAddress(), key.GetType()
-            )
+            key = el[1]
+            child = key.CreateValueFromAddress(f"[{str(index)}]", key.GetLoadAddress(), key.GetType())
             index += 1
 
             self.child_list.append(child)
@@ -559,6 +762,10 @@ class SetCharChildrenProvider:
 
     def update(self):
         self.child_list = []
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+
         cur_pos = 0
         for child in self.value.children:
             child_val = child.signed
@@ -569,9 +776,7 @@ class SetCharChildrenProvider:
                     is_set = temp & 1
                     if is_set == 1:
                         data = lldb.SBData.CreateDataFromInt(cur_pos)
-                        child = self.value.synthetic_child_from_data(
-                            f"[{len(self.child_list)}]", data, self.ty
-                        )
+                        child = self.value.synthetic_child_from_data(f"[{len(self.child_list)}]", data, self.ty)
                         self.child_list.append(child)
                     temp = temp >> 1
                     cur_pos += 1
@@ -584,6 +789,36 @@ class SetCharChildrenProvider:
         return bool(self.num_children())
 
 
+def create_set_children(value: lldb.SBValue, child_type: lldb.SBType, starting_pos: int) -> list[lldb.SBValue]:
+    child_list: list[lldb.SBValue] = []
+    cur_pos = starting_pos
+
+    if value.num_children > 0:
+        children = value.children
+    else:
+        children = [value]
+
+    for child in children:
+        child_val = child.signed
+        if child_val != 0:
+            temp = child_val
+            num_bits = 8
+            while temp != 0:
+                is_set = temp & 1
+                if is_set == 1:
+                    data = lldb.SBData.CreateDataFromInt(cur_pos)
+                    child = value.synthetic_child_from_data(f"[{len(child_list)}]", data, child_type)
+                    child_list.append(child)
+                temp = temp >> 1
+                cur_pos += 1
+                num_bits -= 1
+            cur_pos += num_bits
+        else:
+            cur_pos += 8
+
+    return child_list
+
+
 class SetIntChildrenProvider:
     def __init__(self, value: lldb.SBValue, internalDict):
         self.value = value
@@ -602,34 +837,12 @@ class SetIntChildrenProvider:
 
     def update(self):
         self.child_list = []
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
         bits = self.value.GetByteSize() * 8
-
-        cur_pos = -(bits // 2)
-
-        if self.value.num_children > 0:
-            children = self.value.children
-        else:
-            children = [self.value]
-
-        for child in children:
-            child_val = child.signed
-            if child_val != 0:
-                temp = child_val
-                num_bits = 8
-                while temp != 0:
-                    is_set = temp & 1
-                    if is_set == 1:
-                        data = lldb.SBData.CreateDataFromInt(cur_pos)
-                        child = self.value.synthetic_child_from_data(
-                            f"[{len(self.child_list)}]", data, self.ty
-                        )
-                        self.child_list.append(child)
-                    temp = temp >> 1
-                    cur_pos += 1
-                    num_bits -= 1
-                cur_pos += num_bits
-            else:
-                cur_pos += 8
+        starting_pos = -(bits // 2)
+        self.child_list = create_set_children(self.value, self.ty, starting_pos)
 
     def has_children(self):
         return bool(self.num_children())
@@ -653,32 +866,10 @@ class SetUIntChildrenProvider:
 
     def update(self):
         self.child_list = []
-
-        cur_pos = 0
-        if self.value.num_children > 0:
-            children = self.value.children
-        else:
-            children = [self.value]
-
-        for child in children:
-            child_val = child.signed
-            if child_val != 0:
-                temp = child_val
-                num_bits = 8
-                while temp != 0:
-                    is_set = temp & 1
-                    if is_set == 1:
-                        data = lldb.SBData.CreateDataFromInt(cur_pos)
-                        child = self.value.synthetic_child_from_data(
-                            f"[{len(self.child_list)}]", data, self.ty
-                        )
-                        self.child_list.append(child)
-                    temp = temp >> 1
-                    cur_pos += 1
-                    num_bits -= 1
-                cur_pos += num_bits
-            else:
-                cur_pos += 8
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+        self.child_list = create_set_children(self.value, self.ty, starting_pos=0)
 
     def has_children(self):
         return bool(self.num_children())
@@ -687,7 +878,7 @@ class SetUIntChildrenProvider:
 class SetEnumChildrenProvider:
     def __init__(self, value: lldb.SBValue, internalDict):
         self.value = value
-        self.ty = self.value.target.FindFirstType(f"NU64")
+        self.ty = self.value.target.FindFirstType(self.value.type.name.replace("tySet_", ""))
         self.child_list: list[lldb.SBValue] = []
         self.update()
 
@@ -701,33 +892,10 @@ class SetEnumChildrenProvider:
         return self.child_list[index]
 
     def update(self):
-        self.child_list = []
-
-        cur_pos = 0
-        if self.value.num_children > 0:
-            children = self.value.children
-        else:
-            children = [self.value]
-
-        for child in children:
-            child_val = child.unsigned
-            if child_val != 0:
-                temp = child_val
-                num_bits = 8
-                while temp != 0:
-                    is_set = temp & 1
-                    if is_set == 1:
-                        data = lldb.SBData.CreateDataFromInt(cur_pos)
-                        child = self.value.synthetic_child_from_data(
-                            f"[{len(self.child_list)}]", data, self.ty
-                        )
-                        self.child_list.append(child)
-                    temp = temp >> 1
-                    cur_pos += 1
-                    num_bits -= 1
-                cur_pos += num_bits
-            else:
-                cur_pos += 8
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+        self.child_list = create_set_children(self.value, self.ty, starting_pos=0)
 
     def has_children(self):
         return bool(self.num_children())
@@ -738,6 +906,7 @@ class TableChildrenProvider:
         self.value = value
         self.children: OrderedDict[str, int] = OrderedDict()
         self.child_list: list[lldb.SBValue] = []
+
         self.update()
 
     def num_children(self):
@@ -749,12 +918,20 @@ class TableChildrenProvider:
     def get_child_at_index(self, index):
         return self.child_list[index]
 
+    def get_data(self) -> lldb.SBValue:
+        return self.value["data"]["p"]["data"] if NIM_IS_V2 else self.value["data"]["data"]
+
+    def get_len(self) -> lldb.SBValue:
+        return self.value["data"]["len"] if NIM_IS_V2 else self.value["data"]["Sup"]["len"]
+
     def update(self):
         self.child_list = []
-        data = self.value["data"]
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
 
-        tuple_len = int(data["len"].unsigned)
-        tuple = data["p"]["data"]
+        tuple_len = int(self.get_len().unsigned)
+        tuple = self.get_data()
 
         base_data_type = tuple.type.GetArrayElementType()
 
@@ -763,16 +940,15 @@ class TableChildrenProvider:
         index = 0
         for i in range(tuple_len):
             el = cast[i]
-            field0 = int(el["Field0"].unsigned)
+            field0 = int(el[0].unsigned)
             if field0 == 0:
                 continue
-            key = el["Field1"]
-            val = el["Field2"]
-            child = val.CreateValueFromAddress(
-                key.summary, val.GetLoadAddress(), val.GetType()
-            )
+            key = el[1]
+            val = el[2]
+            key_summary = key.summary
+            child = self.value.CreateValueFromAddress(key_summary, val.GetLoadAddress(), val.GetType())
             self.child_list.append(child)
-            self.children[key.summary] = index
+            self.children[key_summary] = index
             index += 1
 
     def has_children(self):
@@ -795,13 +971,22 @@ class StringTableChildrenProvider:
     def get_child_at_index(self, index):
         return self.child_list[index]
 
+    def get_data(self) -> lldb.SBValue:
+        return self.value["data"]["p"]["data"] if NIM_IS_V2 else self.value["data"]["data"]
+
+    def get_len(self) -> lldb.SBValue:
+        return self.value["data"]["len"] if NIM_IS_V2 else self.value["data"]["Sup"]["len"]
+
     def update(self):
         self.children.clear()
         self.child_list = []
-        data = self.value["data"]
 
-        tuple_len = int(data["len"].unsigned)
-        tuple = data["p"]["data"]
+        if is_local(self.value):
+            if not is_in_scope(self.value):
+                return
+
+        tuple_len = int(self.get_len().unsigned)
+        tuple = self.get_data()
 
         base_data_type = tuple.type.GetArrayElementType()
 
@@ -810,31 +995,67 @@ class StringTableChildrenProvider:
         index = 0
         for i in range(tuple_len):
             el = cast[i]
-            field0 = int(el["Field2"].unsigned)
+            field0 = int(el[2].unsigned)
             if field0 == 0:
                 continue
-            key = el["Field0"]
-            val = el["Field1"]
-            child = val.CreateValueFromAddress(
-                key.summary, val.GetLoadAddress(), val.GetType()
-            )
+            key = el[0]
+            val = el[1]
+            child = val.CreateValueFromAddress(key.summary, val.GetLoadAddress(), val.GetType())
             self.child_list.append(child)
             self.children[key.summary] = index
             index += 1
 
+        self.child_list.append(self.value["mode"])
+        self.children["mode"] = index
+
     def has_children(self):
         return bool(self.num_children())
 
 
-class CustomObjectChildrenProvider:
+class LLDBDynamicObjectProvider:
     def __init__(self, value: lldb.SBValue, internalDict):
-        print("CUSTOMOBJ: ", value.name)
-        self.value: lldb.SBValue = get_synthetic(value) or value
-        for child in self.value.children:
-            print(child)
+        value = value.GetNonSyntheticValue()
+        self.value: lldb.SBValue = value[0]
+        self.children: OrderedDict[str, int] = OrderedDict()
+        self.child_list: list[lldb.SBValue] = []
+
+        while self.value.type.is_pointer:
+            self.value = self.value.Dereference()
+
+        self.update()
 
     def num_children(self):
-        return self.value.num_children
+        return len(self.child_list)
+
+    def get_child_index(self, name: str):
+        return self.children[name]
+
+    def get_child_at_index(self, index):
+        return self.child_list[index]
+
+    def update(self):
+        self.children.clear()
+        self.child_list = []
+
+        for i, child in enumerate(self.value.children):
+            name = child.name.strip('"')
+            new_child = child.CreateValueFromAddress(name, child.GetLoadAddress(), child.GetType())
+
+            self.children[name] = i
+            self.child_list.append(new_child)
+
+    def has_children(self):
+        return bool(self.num_children())
+
+
+class LLDBBasicObjectProvider:
+    def __init__(self, value: lldb.SBValue, internalDict):
+        self.value: lldb.SBValue = value
+
+    def num_children(self):
+        if self.value is not None:
+            return self.value.num_children
+        return 0
 
     def get_child_index(self, name: str):
         return self.value.GetIndexOfChildWithName(name)
@@ -849,6 +1070,35 @@ class CustomObjectChildrenProvider:
         return self.num_children() > 0
 
 
+class CustomObjectChildrenProvider:
+    """
+    This children provider handles values returned from lldbDebugSynthetic*
+    Nim procedures
+    """
+
+    def __init__(self, value: lldb.SBValue, internalDict):
+        self.value: lldb.SBValue = get_custom_synthetic(value) or value
+        if "lldbdynamicobject" in self.value.type.name.lower():
+            self.provider = LLDBDynamicObjectProvider(self.value, internalDict)
+        else:
+            self.provider = LLDBBasicObjectProvider(self.value, internalDict)
+
+    def num_children(self):
+        return self.provider.num_children()
+
+    def get_child_index(self, name: str):
+        return self.provider.get_child_index(name)
+
+    def get_child_at_index(self, index):
+        return self.provider.get_child_at_index(index)
+
+    def update(self):
+        self.provider.update()
+
+    def has_children(self):
+        return self.provider.has_children()
+
+
 def echo(debugger: lldb.SBDebugger, command: str, result, internal_dict):
     debugger.HandleCommand("po " + command)
 
@@ -857,16 +1107,48 @@ SUMMARY_FUNCTIONS: dict[str, lldb.SBFunction] = {}
 SYNTHETIC_FUNCTIONS: dict[str, lldb.SBFunction] = {}
 
 
-def get_summary(value: lldb.SBValue) -> Union[str, None]:
+def get_custom_summary(value: lldb.SBValue) -> Union[str, None]:
+    """Get a custom summary if a function exists for it"""
+    value = value.GetNonSyntheticValue()
+    if value.GetAddress().GetOffset() == 0:
+        return None
+
     base_type = get_base_type(value.type)
 
     fn = SUMMARY_FUNCTIONS.get(base_type.name)
     if fn is None:
         return None
 
-    res = executeCommand(
-        f"{fn.name}(*({base_type.GetPointerType().name})" + str(value.GetLoadAddress()) + ");"
-    )
+    fn_type: lldb.SBType = fn.type
+
+    arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
+    first_type = arg_types.GetTypeAtIndex(0)
+
+    while value.type.is_pointer:
+        value = value.Dereference()
+
+    if first_type.is_pointer:
+        command = f"{fn.name}(({first_type.name})" + str(value.GetLoadAddress()) + ");"
+    else:
+        command = f"{fn.name}(*({first_type.GetPointerType().name})" + str(value.GetLoadAddress()) + ");"
+
+    res = executeCommand(command)
+
+    if res.error.fail:
+        return None
+
+    return res.summary.strip('"')
+
+
+def get_custom_value_summary(value: lldb.SBValue) -> Union[str, None]:
+    """Get a custom summary if a function exists for it"""
+
+    fn: lldb.SBFunction = SUMMARY_FUNCTIONS.get(value.type.name)
+    if fn is None:
+        return None
+
+    command = f"{fn.name}(({value.type.name})" + str(value.signed) + ");"
+    res = executeCommand(command)
 
     if res.error.fail:
         return None
@@ -874,78 +1156,141 @@ def get_summary(value: lldb.SBValue) -> Union[str, None]:
     return res.summary.strip('"')
 
 
-def get_synthetic(value: lldb.SBValue) -> Union[lldb.SBValue, None]:
+def get_custom_synthetic(value: lldb.SBValue) -> Union[lldb.SBValue, None]:
+    """Get a custom synthetic object if a function exists for it"""
+    value = value.GetNonSyntheticValue()
+    if value.GetAddress().GetOffset() == 0:
+        return None
+
     base_type = get_base_type(value.type)
 
     fn = SYNTHETIC_FUNCTIONS.get(base_type.name)
     if fn is None:
         return None
 
-    res = executeCommand(
-        f"{fn.name}(*({base_type.GetPointerType().name})" + str(value.GetLoadAddress()) + ");"
-    )
+    fn_type: lldb.SBType = fn.type
+
+    arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
+    first_type = arg_types.GetTypeAtIndex(0)
+
+    while value.type.is_pointer:
+        value = value.Dereference()
+
+    if first_type.is_pointer:
+        first_arg = f"({first_type.name}){value.GetLoadAddress()}"
+    else:
+        first_arg = f"*({first_type.GetPointerType().name}){value.GetLoadAddress()}"
+
+    if arg_types.GetSize() > 1 and fn.GetArgumentName(1) == "Result":
+        ret_type = arg_types.GetTypeAtIndex(1)
+        ret_type = get_base_type(ret_type)
+
+        command = f"""
+            {ret_type.name} lldbT;
+            nimZeroMem((void*)(&lldbT), sizeof({ret_type.name}));
+            {fn.name}(({first_arg}), (&lldbT));
+            lldbT;
+        """
+    else:
+        command = f"{fn.name}({first_arg});"
+
+    res = executeCommand(command)
 
     if res.error.fail:
+        print(res.error)
         return None
 
     return res
 
 
 def get_base_type(ty: lldb.SBType) -> lldb.SBType:
+    """Get the base type of the type"""
     temp = ty
     while temp.IsPointerType():
         temp = temp.GetPointeeType()
     return temp
 
 
+def use_base_type(ty: lldb.SBType) -> bool:
+    types_to_check = [
+        "NF",
+        "NF32",
+        "NF64",
+        "NI",
+        "NI8",
+        "NI16",
+        "NI32",
+        "NI64",
+        "bool",
+        "NIM_BOOL",
+        "NU",
+        "NU8",
+        "NU16",
+        "NU32",
+        "NU64",
+    ]
+
+    for type_to_check in types_to_check:
+        if ty.name.startswith(type_to_check):
+            return False
+
+    return True
+
+
 def breakpoint_function_wrapper(frame: lldb.SBFrame, bp_loc, internal_dict):
     """This allows function calls to Nim for custom object summaries and synthetic children"""
     debugger = lldb.debugger
 
     global SUMMARY_FUNCTIONS
     global SYNTHETIC_FUNCTIONS
+
+    global NIM_IS_V2
+
     for tname, fn in SYNTHETIC_FUNCTIONS.items():
-        print("DELETING SYNTH: ", tname)
         debugger.HandleCommand(f"type synthetic delete -w nim {tname}")
 
     SUMMARY_FUNCTIONS = {}
     SYNTHETIC_FUNCTIONS = {}
 
     target: lldb.SBTarget = debugger.GetSelectedTarget()
-    print("BREAKPOINT")
+
+    NIM_IS_V2 = target.FindFirstType("TNimTypeV2").IsValid()
+
     module = frame.GetSymbolContext(lldb.eSymbolContextModule).module
 
     for sym in module:
-        if not sym.name.startswith("lldbDebugSummary") and not sym.name.startswith(
-            "lldbDebugSynthetic"
+        if (
+            not sym.name.startswith("lldbDebugSummary")
+            and not sym.name.startswith("lldbDebugSynthetic")
+            and not sym.name.startswith("dollar___")
         ):
             continue
 
-        print("SYM: ", sym.name)
-
         fn_syms: lldb.SBSymbolContextList = target.FindFunctions(sym.name)
         if not fn_syms.GetSize() > 0:
             continue
-        fn_sym: lldb.SBSymbolContext = fn_syms.GetContextAtIndex(0)
 
-        print("fn found!")
+        fn_sym: lldb.SBSymbolContext = fn_syms.GetContextAtIndex(0)
 
         fn: lldb.SBFunction = fn_sym.function
         fn_type: lldb.SBType = fn.type
         arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
 
-        if not arg_types.GetSize() > 0:
+        if arg_types.GetSize() > 1 and fn.GetArgumentName(1) == "Result":
+            pass # don't continue
+        elif arg_types.GetSize() != 1:
             continue
-        arg_type: lldb.SBType = get_base_type(arg_types.GetTypeAtIndex(0))
 
-        print("FIRST ARG TYPE: ", arg_type.name)
+        arg_type: lldb.SBType = arg_types.GetTypeAtIndex(0)
+        if use_base_type(arg_type):
+            arg_type = get_base_type(arg_type)
 
-        if sym.name.startswith("lldbDebugSummary"):
+        if sym.name.startswith("lldbDebugSummary") or sym.name.startswith("dollar___"):
             SUMMARY_FUNCTIONS[arg_type.name] = fn
         elif sym.name.startswith("lldbDebugSynthetic"):
             SYNTHETIC_FUNCTIONS[arg_type.name] = fn
             debugger.HandleCommand(
-                f"type synthetic add -w nim -l {__name__}.CustomObjectChildrenProvider -x {arg_type.name}$"
+                f"type synthetic add -w nim -l {__name__}.CustomObjectChildrenProvider {arg_type.name}"
             )
 
 
@@ -953,10 +1298,6 @@ def executeCommand(command, *args):
     debugger = lldb.debugger
     process = debugger.GetSelectedTarget().GetProcess()
     frame: lldb.SBFrame = process.GetSelectedThread().GetSelectedFrame()
-    # module = frame.GetSymbolContext(lldb.eSymbolContextModule).module
-    # for sym in module:
-    #     print("SYM: ", sym.name)
-    # target = debugger.GetSelectedTarget()
 
     expr_options = lldb.SBExpressionOptions()
     expr_options.SetIgnoreBreakpoints(False)
@@ -968,24 +1309,24 @@ def executeCommand(command, *args):
     expr_options.SetLanguage(lldb.eLanguageTypeC)
     expr_options.SetCoerceResultToId(True)
     res = frame.EvaluateExpression(command, expr_options)
-    # if res.error.fail:
-    #     print("ERROR: ", res.error.GetError())
-    #     return str(res.error)
+
     return res
 
 
 def __lldb_init_module(debugger, internal_dict):
-    # debugger.HandleCommand(f"type summary add -w nim -n any -F  {__name__}.CatchAll -x .*")
+    # fmt: off
+    debugger.HandleCommand(f"breakpoint command add -F {__name__}.breakpoint_function_wrapper --script-type python 1")
     debugger.HandleCommand(f"type summary add -w nim -n sequence -F  {__name__}.Sequence -x tySequence_+[[:alnum:]]+$")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SeqChildrenProvider -x tySequence_+[[:alnum:]]+$")
 
     debugger.HandleCommand(f"type summary add -w nim -n chararray -F  {__name__}.CharArray -x char\s+[\d+]")
     debugger.HandleCommand(f"type summary add -w nim -n array -F  {__name__}.Array -x tyArray_+[[:alnum:]]+")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.ArrayChildrenProvider -x tyArray_+[[:alnum:]]+")
-    debugger.HandleCommand(f"type summary add -w nim -n string -F  {__name__}.NimStringDesc NimStringDesc")
+    debugger.HandleCommand(f"type summary add -w nim -n string -F  {__name__}.NimString NimStringDesc")
 
-    debugger.HandleCommand(f"type summary add -w nim -n stringv2 -F {__name__}.NimStringV2 -x NimStringV2$")
+    debugger.HandleCommand(f"type summary add -w nim -n stringv2 -F {__name__}.NimString -x NimStringV2$")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringChildrenProvider -x NimStringV2$")
+    debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringChildrenProvider -x NimStringDesc$")
 
     debugger.HandleCommand(f"type summary add -w nim -n cstring -F  {__name__}.NCSTRING NCSTRING")
 
@@ -999,6 +1340,9 @@ def __lldb_init_module(debugger, internal_dict):
     debugger.HandleCommand(f"type summary add -w nim -n enum -F  {__name__}.Enum -x tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n hashset -F  {__name__}.HashSet -x tyObject_+HashSet_+[[:alnum:]]+")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.HashSetChildrenProvider -x tyObject_+HashSet_+[[:alnum:]]+")
+
+    debugger.HandleCommand(f"type summary add -w nim -n rope -F  {__name__}.Rope -x tyObject_+Rope[[:alnum:]]+_+[[:alnum:]]+")
+
     debugger.HandleCommand(f"type summary add -w nim -n setuint -F  {__name__}.Set -x tySet_+tyInt_+[[:alnum:]]+")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetIntChildrenProvider -x tySet_+tyInt[0-9]+_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n setint -F  {__name__}.Set -x tySet_+tyInt[0-9]+_+[[:alnum:]]+")
@@ -1006,7 +1350,7 @@ def __lldb_init_module(debugger, internal_dict):
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetUIntChildrenProvider -x tySet_+tyUInt[0-9]+_+[[:alnum:]]+")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetUIntChildrenProvider -x tySet_+tyInt_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n setenum -F  {__name__}.EnumSet -x tySet_+tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
-    debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetUIntChildrenProvider -x tySet_+tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
+    debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetEnumChildrenProvider -x tySet_+tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n setchar -F  {__name__}.Set -x tySet_+tyChar_+[[:alnum:]]+")
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetCharChildrenProvider -x tySet_+tyChar_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n table -F  {__name__}.Table -x tyObject_+Table_+[[:alnum:]]+")
@@ -1015,9 +1359,7 @@ def __lldb_init_module(debugger, internal_dict):
     debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringTableChildrenProvider -x tyObject_+StringTableObj_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n tuple2 -F  {__name__}.Tuple -x tyObject_+Tuple_+[[:alnum:]]+")
     debugger.HandleCommand(f"type summary add -w nim -n tuple -F  {__name__}.Tuple -x tyTuple_+[[:alnum:]]+")
-    # debugger.HandleCommand(f"type summary add -w nim -n TNimType -F  {__name__}.Object TNimType")
-    debugger.HandleCommand(f"type summary add -w nim -n TNimTypeV2 -F  {__name__}.ObjectV2 TNimTypeV2")
-    # debugger.HandleCommand(f"type summary add -w nim -n TNimNode -F  {__name__}.Object TNimNode")
+
     debugger.HandleCommand(f"type summary add -w nim -n float -F  {__name__}.Float NF")
     debugger.HandleCommand(f"type summary add -w nim -n float32 -F  {__name__}.Float NF32")
     debugger.HandleCommand(f"type summary add -w nim -n float64 -F  {__name__}.Float NF64")
@@ -1035,5 +1377,4 @@ def __lldb_init_module(debugger, internal_dict):
     debugger.HandleCommand(f"type summary add -w nim -n uinteger64 -F  {__name__}.UnsignedNumber -x NU64")
     debugger.HandleCommand("type category enable nim")
     debugger.HandleCommand(f"command script add -f  {__name__}.echo echo")
-    debugger.HandleCommand(f"command script add -f {__name__}.handle_command ddp")
-    debugger.HandleCommand(f"breakpoint command add -F {__name__}.breakpoint_function_wrapper --script-type python 1")
\ No newline at end of file
+    # fmt: on