Files
Nim/tools/debug/nim-lldb.py
Arnaud Moura b2c5f8a05f fixes #21461 (#21463)
* fixes #21461; Move nim-gdb.py and add nim-lldb.py

* fixes bad path for nim-gdb.py
2023-03-03 23:37:12 +01:00

1039 lines
34 KiB
Python

import lldb
from collections import OrderedDict
from typing import Union
def sbvaluegetitem(self: lldb.SBValue, name: Union[int, str]) -> lldb.SBValue:
if isinstance(name, str):
return self.GetChildMemberWithName(name)
else:
return self.GetChildAtIndex(name)
# Make this easier to work with
lldb.SBValue.__getitem__ = sbvaluegetitem
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"""
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:
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"
)
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 to_string(value):
# For getting NimStringDesc * value
data = value["data"]
try:
size = int(value["Sup"]["len"].unsigned)
if size > 2**14:
return None
except TypeError:
return None
cast = data.Cast(value.target.FindFirstType("char").GetArrayType(size))
return bytearray(cast.data.uint8s).decode("utf-8")
def to_stringV2(value: lldb.SBValue):
# For getting NimStringDesc * value
data = value["p"]["data"]
try:
size = int(value["len"].signed)
if size > 2**14:
return "... (too long)"
except TypeError:
return ""
base_data_type = data.type.GetArrayElementType().GetTypedefedType()
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 NimStringV2(value: lldb.SBValue, internal_dict):
res = to_stringV2(value.GetNonSyntheticValue())
if res is not None:
return colored('"' + res + '"', "red")
else:
return str(value)
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 ObjectV1(value, internal_dict):
if not value.num_children and not value.value:
return ""
ignore_fields = set()
if "colonObjectType" in value.type.name:
value = value.Dereference()
ignore_fields.add("Sup")
if not value.type.name:
return ""
summary = value.summary
if summary is not None:
return summary
if "_" in value.type.name:
obj_name = value.type.name.split("_")[1].replace("colonObjectType", "")
else:
obj_name = value.type.name
obj_name = colored(obj_name, "green")
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 ObjectV2(value: lldb.SBValue, internal_dict):
custom_summary = get_summary(value)
if not custom_summary is None:
return custom_summary
orig_value = value.GetNonSyntheticValue()
while orig_value.type.is_pointer:
orig_value = orig_value.Dereference()
if "_" in orig_value.type.name:
obj_name = orig_value.type.name.split("_")[1].replace("colonObjectType", "")
else:
obj_name = orig_value.type.name
num_children = value.num_children
fields = []
for i in range(num_children):
fields.append(f"{value[i].name}: {value[i].summary}")
res = f"{obj_name}(" + ", ".join(fields) + ")"
return res
def Number(value: lldb.SBValue, internal_dict):
while value.type.is_pointer:
value = value.Dereference()
return colored(str(value.signed), "yellow")
def Float(value: lldb.SBValue, internal_dict):
while value.type.is_pointer:
value = value.Dereference()
return colored(str(value.value), "yellow")
def UnsignedNumber(value: lldb.SBValue, internal_dict):
while value.type.is_pointer:
value = value.Dereference()
return colored(str(value.unsigned), "yellow")
def Bool(value: lldb.SBValue, internal_dict):
while value.type.is_pointer:
value = value.Dereference()
return colored(str(value.GetValue()), "red")
def CharArray(value: lldb.SBValue, internal_dict):
return str([colored(f"'{char}'", "red") for char in value.uint8s])
def Array(value: lldb.SBValue, internal_dict):
value = value.GetNonSyntheticValue()
return "[" + ", ".join([value[i].summary for i in range(value.num_children)]) + "]"
def Tuple(value: lldb.SBValue, internal_dict):
while value.type.is_pointer:
value = value.Dereference()
num_children = value.num_children
fields = []
for i in range(num_children):
key = value[i].name
val = value[i].summary
if key.startswith("Field"):
fields.append(f"{val}")
else:
fields.append(f"{key}: {val}")
return "(" + ", ".join(fields) + f")"
def Enum(value, internal_dict):
tname = value.type.name.split("_")[1]
return colored(f"{tname}." + str(value.signed), "blue")
def EnumSet(value, internal_dict):
type_nim_name = value.type.name.split("_")[2]
# type_nim_name, nti = get_nti(value, type_nim_name)
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 Set(value, internal_dict):
vals = []
max_vals = 7
for child in value.children:
vals.append(child.value)
if len(vals) > max_vals:
vals.append("...")
break
return "{" + ", ".join(vals) + "}"
def Table(value: lldb.SBValue, internal_dict):
fields = []
for i in range(value.num_children):
key = value[i].name
val = value[i].summary
fields.append(f"{key}: {val}")
table_suffix = "Table"
return "{" + ", ".join(fields) + f"}}.{table_suffix}"
def HashSet(value: lldb.SBValue, internal_dict):
fields = []
for i in range(value.num_children):
fields.append(f"{value[i].summary}")
table_suffix = "HashSet"
return "{" + ", ".join(fields) + f"}}.{table_suffix}"
def StringTable(value: lldb.SBValue, internal_dict):
table = value.GetNonSyntheticValue()
mode = table["mode"].unsigned
table_suffix = "StringTable"
table_mode = ""
if mode == 0:
table_mode = "Case Sensitive"
elif mode == 1:
table_mode = "Case Insensitive"
elif mode == 2:
table_mode = "Style Insensitive"
fields = []
for i in range(value.num_children):
key = value[i].name
val = value[i].summary
fields.append(f"{key}: {val}")
return "{" + ", ".join(fields) + f"}}.{table_suffix}({table_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()
cast = data.Cast(base_data_type.GetArrayType(data_len))
return (
"@["
+ ", ".join([cast[i].summary or cast[i].type.name for i in range(data_len)])
+ "]"
)
class StringChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.data_type: lldb.SBType
self.first_element: lldb.SBValue
self.update()
self.count = 0
def num_children(self):
return self.count
def get_child_index(self, name):
return int(name.lstrip("[").rstrip("]"))
def get_child_at_index(self, index):
offset = index * self.data_size
return self.first_element.CreateChildAtOffset(
"[" + str(index) + "]", offset, self.data_type
)
def update(self):
data = self.value["p"]["data"]
size = int(self.value["len"].unsigned)
self.count = size
self.first_element = data
self.data_type = data.type.GetArrayElementType().GetTypedefedType()
self.data_size = self.data_type.GetByteSize()
def has_children(self):
return bool(self.num_children())
class ArrayChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.data_type: lldb.SBType
self.first_element: lldb.SBValue
self.update()
def num_children(self):
return 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
)
def update(self):
if not self.has_children():
return
self.first_element = self.value[0]
self.data_type = self.value.type.GetArrayElementType()
def has_children(self):
return bool(self.num_children())
class SeqChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.data_type: lldb.SBType
self.first_element: lldb.SBValue
self.data: lldb.SBValue
self.update()
def num_children(self):
return int(self.value["len"].unsigned)
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
)
def update(self):
if not self.has_children():
return
data = self.value["p"]["data"]
self.data_type = data.type.GetArrayElementType()
self.data = data.Cast(self.data_type.GetArrayType(self.num_children()))
self.first_element = self.data
def has_children(self):
return bool(self.num_children())
class ObjectChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.data_type: lldb.SBType
self.first_element: lldb.SBValue
self.data: lldb.SBValue
self.children: OrderedDict[str, int] = OrderedDict()
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
return len(self.children)
def get_child_index(self, name: str):
return self.children[name]
def get_child_at_index(self, index):
return self.child_list[index]
def populate_children(self):
self.children.clear()
self.child_list = []
stack = [self.value]
index = 0
while stack:
cur_val = stack.pop()
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")
):
stack.append(cur_val[0])
for i in range(cur_val.num_children):
child = cur_val[i]
if child.name == "Sup":
continue
self.children[child.name] = index
self.child_list.append(child)
index += 1
def update(self):
self.populate_children()
def has_children(self):
return bool(self.num_children())
class HashSetChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
return len(self.child_list)
def get_child_index(self, name: str):
return int(name.lstrip("[").rstrip("]"))
def get_child_at_index(self, index):
return self.child_list[index]
def update(self):
self.child_list = []
data = self.value["data"]
tuple_len = int(data["len"].unsigned)
tuple = data["p"]["data"]
base_data_type = tuple.type.GetArrayElementType()
cast = tuple.Cast(base_data_type.GetArrayType(tuple_len))
index = 0
for i in range(tuple_len):
el = cast[i]
field0 = int(el["Field0"].unsigned)
if field0 == 0:
continue
key = el["Field1"]
child = key.CreateValueFromAddress(
f"[{str(index)}]", key.GetLoadAddress(), key.GetType()
)
index += 1
self.child_list.append(child)
def has_children(self):
return bool(self.num_children())
class SetCharChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.ty = self.value.target.FindFirstType("char")
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
return len(self.child_list)
def get_child_index(self, name: str):
return int(name.lstrip("[").rstrip("]"))
def get_child_at_index(self, index):
return self.child_list[index]
def update(self):
self.child_list = []
cur_pos = 0
for child in self.value.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
def has_children(self):
return bool(self.num_children())
class SetIntChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.ty = self.value.target.FindFirstType(f"NI64")
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
return len(self.child_list)
def get_child_index(self, name: str):
return int(name.lstrip("[").rstrip("]"))
def get_child_at_index(self, index):
return self.child_list[index]
def update(self):
self.child_list = []
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
def has_children(self):
return bool(self.num_children())
class SetUIntChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.ty = self.value.target.FindFirstType(f"NU64")
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
return len(self.child_list)
def get_child_index(self, name: str):
return int(name.lstrip("[").rstrip("]"))
def get_child_at_index(self, index):
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.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
def has_children(self):
return bool(self.num_children())
class SetEnumChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.ty = self.value.target.FindFirstType(f"NU64")
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
return len(self.child_list)
def get_child_index(self, name: str):
return int(name.lstrip("[").rstrip("]"))
def get_child_at_index(self, index):
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
def has_children(self):
return bool(self.num_children())
class TableChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.children: OrderedDict[str, int] = OrderedDict()
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
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.child_list = []
data = self.value["data"]
tuple_len = int(data["len"].unsigned)
tuple = data["p"]["data"]
base_data_type = tuple.type.GetArrayElementType()
cast = tuple.Cast(base_data_type.GetArrayType(tuple_len))
index = 0
for i in range(tuple_len):
el = cast[i]
field0 = int(el["Field0"].unsigned)
if field0 == 0:
continue
key = el["Field1"]
val = el["Field2"]
child = val.CreateValueFromAddress(
key.summary, val.GetLoadAddress(), val.GetType()
)
self.child_list.append(child)
self.children[key.summary] = index
index += 1
def has_children(self):
return bool(self.num_children())
class StringTableChildrenProvider:
def __init__(self, value: lldb.SBValue, internalDict):
self.value = value
self.children: OrderedDict[str, int] = OrderedDict()
self.child_list: list[lldb.SBValue] = []
self.update()
def num_children(self):
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 = []
data = self.value["data"]
tuple_len = int(data["len"].unsigned)
tuple = data["p"]["data"]
base_data_type = tuple.type.GetArrayElementType()
cast = tuple.Cast(base_data_type.GetArrayType(tuple_len))
index = 0
for i in range(tuple_len):
el = cast[i]
field0 = int(el["Field2"].unsigned)
if field0 == 0:
continue
key = el["Field0"]
val = el["Field1"]
child = val.CreateValueFromAddress(
key.summary, val.GetLoadAddress(), val.GetType()
)
self.child_list.append(child)
self.children[key.summary] = index
index += 1
def has_children(self):
return bool(self.num_children())
class CustomObjectChildrenProvider:
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)
def num_children(self):
return self.value.num_children
def get_child_index(self, name: str):
return self.value.GetIndexOfChildWithName(name)
def get_child_at_index(self, index):
return self.value.GetChildAtIndex(index)
def update(self):
pass
def has_children(self):
return self.num_children() > 0
def echo(debugger: lldb.SBDebugger, command: str, result, internal_dict):
debugger.HandleCommand("po " + command)
SUMMARY_FUNCTIONS: dict[str, lldb.SBFunction] = {}
SYNTHETIC_FUNCTIONS: dict[str, lldb.SBFunction] = {}
def get_summary(value: lldb.SBValue) -> Union[str, 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()) + ");"
)
if res.error.fail:
return None
return res.summary.strip('"')
def get_synthetic(value: lldb.SBValue) -> Union[lldb.SBValue, 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()) + ");"
)
if res.error.fail:
return None
return res
def get_base_type(ty: lldb.SBType) -> lldb.SBType:
temp = ty
while temp.IsPointerType():
temp = temp.GetPointeeType()
return temp
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
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")
module = frame.GetSymbolContext(lldb.eSymbolContextModule).module
for sym in module:
if not sym.name.startswith("lldbDebugSummary") and not sym.name.startswith(
"lldbDebugSynthetic"
):
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: lldb.SBFunction = fn_sym.function
fn_type: lldb.SBType = fn.type
arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
if not arg_types.GetSize() > 0:
continue
arg_type: lldb.SBType = get_base_type(arg_types.GetTypeAtIndex(0))
print("FIRST ARG TYPE: ", arg_type.name)
if sym.name.startswith("lldbDebugSummary"):
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}$"
)
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)
expr_options.SetFetchDynamicValue(lldb.eDynamicCanRunTarget)
expr_options.SetTimeoutInMicroSeconds(30 * 1000 * 1000) # 30 second timeout
expr_options.SetTryAllThreads(True)
expr_options.SetUnwindOnError(False)
expr_options.SetGenerateDebugInfo(True)
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 .*")
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 stringv2 -F {__name__}.NimStringV2 -x NimStringV2$")
debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringChildrenProvider -x NimStringV2$")
debugger.HandleCommand(f"type summary add -w nim -n cstring -F {__name__}.NCSTRING NCSTRING")
debugger.HandleCommand(f"type summary add -w nim -n object -F {__name__}.ObjectV2 -x tyObject_+[[:alnum:]]+_+[[:alnum:]]+")
debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.ObjectChildrenProvider -x tyObject_+[[:alnum:]]+_+[[:alnum:]]+$")
debugger.HandleCommand(f"type summary add -w nim -n tframe -F {__name__}.ObjectV2 -x TFrame$")
debugger.HandleCommand(f"type summary add -w nim -n rootobj -F {__name__}.ObjectV2 -x RootObj$")
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 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:]]+")
debugger.HandleCommand(f"type summary add -w nim -n setuint2 -F {__name__}.Set -x tySet_+tyUInt[0-9]+_+[[:alnum:]]+")
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 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:]]+")
debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.TableChildrenProvider -x tyObject_+Table_+[[:alnum:]]+")
debugger.HandleCommand(f"type summary add -w nim -n stringtable -F {__name__}.StringTable -x tyObject_+StringTableObj_+[[:alnum:]]+")
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")
debugger.HandleCommand(f"type summary add -w nim -n integer -F {__name__}.Number -x NI")
debugger.HandleCommand(f"type summary add -w nim -n integer8 -F {__name__}.Number -x NI8")
debugger.HandleCommand(f"type summary add -w nim -n integer16 -F {__name__}.Number -x NI16")
debugger.HandleCommand(f"type summary add -w nim -n integer32 -F {__name__}.Number -x NI32")
debugger.HandleCommand(f"type summary add -w nim -n integer64 -F {__name__}.Number -x NI64")
debugger.HandleCommand(f"type summary add -w nim -n bool -F {__name__}.Bool -x bool")
debugger.HandleCommand(f"type summary add -w nim -n bool2 -F {__name__}.Bool -x NIM_BOOL")
debugger.HandleCommand(f"type summary add -w nim -n uinteger -F {__name__}.UnsignedNumber -x NU")
debugger.HandleCommand(f"type summary add -w nim -n uinteger8 -F {__name__}.UnsignedNumber -x NU8")
debugger.HandleCommand(f"type summary add -w nim -n uinteger16 -F {__name__}.UnsignedNumber -x NU16")
debugger.HandleCommand(f"type summary add -w nim -n uinteger32 -F {__name__}.UnsignedNumber -x NU32")
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")