nimlldb.py 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381
  1. import lldb
  2. from collections import OrderedDict
  3. from typing import Union
  4. def sbvaluegetitem(self: lldb.SBValue, name: Union[int, str]) -> lldb.SBValue:
  5. if isinstance(name, str):
  6. return self.GetChildMemberWithName(name)
  7. else:
  8. return self.GetChildAtIndex(name)
  9. # Make this easier to work with
  10. lldb.SBValue.__getitem__ = sbvaluegetitem
  11. NIM_IS_V2 = True
  12. def get_nti(value: lldb.SBValue, nim_name=None):
  13. name_split = value.type.name.split("_")
  14. type_nim_name = nim_name or name_split[1]
  15. id_string = name_split[-1].split(" ")[0]
  16. type_info_name = "NTI" + type_nim_name.lower() + "__" + id_string + "_"
  17. nti = value.target.FindFirstGlobalVariable(type_info_name)
  18. if not nti.IsValid():
  19. type_info_name = "NTI" + "__" + id_string + "_"
  20. nti = value.target.FindFirstGlobalVariable(type_info_name)
  21. if not nti.IsValid():
  22. print(f"NimEnumPrinter: lookup global symbol: '{type_info_name}' failed for {value.type.name}.\n")
  23. return type_nim_name, nti
  24. def enum_to_string(value: lldb.SBValue, int_val=None, nim_name=None):
  25. tname = nim_name or value.type.name.split("_")[1]
  26. enum_val = value.signed
  27. if int_val is not None:
  28. enum_val = int_val
  29. default_val = f"{tname}.{str(enum_val)}"
  30. fn_syms = value.target.FindFunctions("reprEnum")
  31. if not fn_syms.GetSize() > 0:
  32. return default_val
  33. fn_sym: lldb.SBSymbolContext = fn_syms.GetContextAtIndex(0)
  34. fn: lldb.SBFunction = fn_sym.function
  35. fn_type: lldb.SBType = fn.type
  36. arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
  37. if arg_types.GetSize() < 2:
  38. return default_val
  39. arg1_type: lldb.SBType = arg_types.GetTypeAtIndex(0)
  40. arg2_type: lldb.SBType = arg_types.GetTypeAtIndex(1)
  41. ty_info_name, nti = get_nti(value, nim_name=tname)
  42. if not nti.IsValid():
  43. return default_val
  44. call = f"{fn.name}(({arg1_type.name}){enum_val}, ({arg2_type.name})" + str(nti.GetLoadAddress()) + ");"
  45. res = executeCommand(call)
  46. if res.error.fail:
  47. return default_val
  48. return f"{tname}.{res.summary[1:-1]}"
  49. def to_string(value: lldb.SBValue):
  50. # For getting NimStringDesc * value
  51. value = value.GetNonSyntheticValue()
  52. # Check if data pointer is Null
  53. if value.type.is_pointer and value.unsigned == 0:
  54. return None
  55. size = int(value["Sup"]["len"].unsigned)
  56. if size == 0:
  57. return ""
  58. if size > 2**14:
  59. return "... (too long) ..."
  60. data = value["data"]
  61. # Check if first element is NULL
  62. base_data_type = value.target.FindFirstType("char")
  63. cast = data.Cast(base_data_type)
  64. if cast.unsigned == 0:
  65. return None
  66. cast = data.Cast(value.target.FindFirstType("char").GetArrayType(size))
  67. return bytearray(cast.data.uint8s).decode("utf-8")
  68. def to_stringV2(value: lldb.SBValue):
  69. # For getting NimStringV2 value
  70. value = value.GetNonSyntheticValue()
  71. data = value["p"]["data"]
  72. # Check if data pointer is Null
  73. if value["p"].unsigned == 0:
  74. return None
  75. size = int(value["len"].signed)
  76. if size == 0:
  77. return ""
  78. if size > 2**14:
  79. return "... (too long) ..."
  80. # Check if first element is NULL
  81. base_data_type = data.type.GetArrayElementType().GetTypedefedType()
  82. cast = data.Cast(base_data_type)
  83. if cast.unsigned == 0:
  84. return None
  85. cast = data.Cast(base_data_type.GetArrayType(size))
  86. return bytearray(cast.data.uint8s).decode("utf-8")
  87. def NimString(value: lldb.SBValue, internal_dict):
  88. if is_local(value):
  89. if not is_in_scope(value):
  90. return "undefined"
  91. custom_summary = get_custom_summary(value)
  92. if not custom_summary is None:
  93. return custom_summary
  94. if NIM_IS_V2:
  95. res = to_stringV2(value)
  96. else:
  97. res = to_string(value)
  98. if res is not None:
  99. return f'"{res}"'
  100. else:
  101. return "nil"
  102. def rope_helper(value: lldb.SBValue) -> str:
  103. value = value.GetNonSyntheticValue()
  104. if value.type.is_pointer and value.unsigned == 0:
  105. return ""
  106. if value["length"].unsigned == 0:
  107. return ""
  108. if NIM_IS_V2:
  109. str_val = to_stringV2(value["data"])
  110. else:
  111. str_val = to_string(value["data"])
  112. if str_val is None:
  113. str_val = ""
  114. return rope_helper(value["left"]) + str_val + rope_helper(value["right"])
  115. def Rope(value: lldb.SBValue, internal_dict):
  116. if is_local(value):
  117. if not is_in_scope(value):
  118. return "undefined"
  119. custom_summary = get_custom_summary(value)
  120. if not custom_summary is None:
  121. return custom_summary
  122. rope_str = rope_helper(value)
  123. if len(rope_str) == 0:
  124. rope_str = "nil"
  125. else:
  126. rope_str = f'"{rope_str}"'
  127. return f"Rope({rope_str})"
  128. def NCSTRING(value: lldb.SBValue, internal_dict=None):
  129. if is_local(value):
  130. if not is_in_scope(value):
  131. return "undefined"
  132. ty = value.Dereference().type
  133. val = value.target.CreateValueFromAddress(
  134. value.name or "temp", lldb.SBAddress(value.unsigned, value.target), ty
  135. ).AddressOf()
  136. return val.summary
  137. def ObjectV2(value: lldb.SBValue, internal_dict):
  138. if is_local(value):
  139. if not is_in_scope(value):
  140. return "undefined"
  141. orig_value = value.GetNonSyntheticValue()
  142. if orig_value.type.is_pointer and orig_value.unsigned == 0:
  143. return "nil"
  144. custom_summary = get_custom_summary(value)
  145. if custom_summary is not None:
  146. return custom_summary
  147. while orig_value.type.is_pointer:
  148. orig_value = orig_value.Dereference()
  149. if "_" in orig_value.type.name:
  150. obj_name = orig_value.type.name.split("_")[1].replace("colonObjectType", "")
  151. else:
  152. obj_name = orig_value.type.name
  153. num_children = value.num_children
  154. fields = []
  155. for i in range(num_children):
  156. fields.append(f"{value[i].name}: {value[i].summary}")
  157. res = f"{obj_name}(" + ", ".join(fields) + ")"
  158. return res
  159. def Number(value: lldb.SBValue, internal_dict):
  160. if is_local(value):
  161. if not is_in_scope(value):
  162. return "undefined"
  163. if value.type.is_pointer and value.signed == 0:
  164. return "nil"
  165. custom_summary = get_custom_summary(value)
  166. if not custom_summary is None:
  167. return custom_summary
  168. return str(value.signed)
  169. def Float(value: lldb.SBValue, internal_dict):
  170. if is_local(value):
  171. if not is_in_scope(value):
  172. return "undefined"
  173. custom_summary = get_custom_summary(value)
  174. if not custom_summary is None:
  175. return custom_summary
  176. return str(value.value)
  177. def UnsignedNumber(value: lldb.SBValue, internal_dict):
  178. if is_local(value):
  179. if not is_in_scope(value):
  180. return "undefined"
  181. custom_summary = get_custom_summary(value)
  182. if not custom_summary is None:
  183. return custom_summary
  184. return str(value.unsigned)
  185. def Bool(value: lldb.SBValue, internal_dict):
  186. if is_local(value):
  187. if not is_in_scope(value):
  188. return "undefined"
  189. custom_summary = get_custom_summary(value)
  190. if not custom_summary is None:
  191. return custom_summary
  192. return str(value.value)
  193. def CharArray(value: lldb.SBValue, internal_dict):
  194. if is_local(value):
  195. if not is_in_scope(value):
  196. return "undefined"
  197. custom_summary = get_custom_summary(value)
  198. if not custom_summary is None:
  199. return custom_summary
  200. return str([f"'{char}'" for char in value.uint8s])
  201. def Array(value: lldb.SBValue, internal_dict):
  202. if is_local(value):
  203. if not is_in_scope(value):
  204. return "undefined"
  205. value = value.GetNonSyntheticValue()
  206. custom_summary = get_custom_summary(value)
  207. if not custom_summary is None:
  208. return custom_summary
  209. value = value.GetNonSyntheticValue()
  210. return "[" + ", ".join([value[i].summary for i in range(value.num_children)]) + "]"
  211. def Tuple(value: lldb.SBValue, internal_dict):
  212. if is_local(value):
  213. if not is_in_scope(value):
  214. return "undefined"
  215. custom_summary = get_custom_summary(value)
  216. if not custom_summary is None:
  217. return custom_summary
  218. while value.type.is_pointer:
  219. value = value.Dereference()
  220. num_children = value.num_children
  221. fields = []
  222. for i in range(num_children):
  223. key = value[i].name
  224. val = value[i].summary
  225. if key.startswith("Field"):
  226. fields.append(f"{val}")
  227. else:
  228. fields.append(f"{key}: {val}")
  229. return "(" + ", ".join(fields) + f")"
  230. def is_local(value: lldb.SBValue) -> bool:
  231. line: lldb.SBLineEntry = value.frame.GetLineEntry()
  232. decl: lldb.SBDeclaration = value.GetDeclaration()
  233. if line.file == decl.file and decl.line != 0:
  234. return True
  235. return False
  236. def is_in_scope(value: lldb.SBValue) -> bool:
  237. line: lldb.SBLineEntry = value.frame.GetLineEntry()
  238. decl: lldb.SBDeclaration = value.GetDeclaration()
  239. if is_local(value) and decl.line < line.line:
  240. return True
  241. return False
  242. def Enum(value: lldb.SBValue, internal_dict):
  243. if is_local(value):
  244. if not is_in_scope(value):
  245. return "undefined"
  246. custom_summary = get_custom_value_summary(value)
  247. if custom_summary is not None:
  248. return custom_summary
  249. return enum_to_string(value)
  250. def EnumSet(value: lldb.SBValue, internal_dict):
  251. if is_local(value):
  252. if not is_in_scope(value):
  253. return "undefined"
  254. custom_summary = get_custom_summary(value)
  255. if not custom_summary is None:
  256. return custom_summary
  257. vals = []
  258. max_vals = 7
  259. for child in value.children:
  260. vals.append(child.summary)
  261. if len(vals) > max_vals:
  262. vals.append("...")
  263. break
  264. return "{" + ", ".join(vals) + "}"
  265. def Set(value: lldb.SBValue, internal_dict):
  266. if is_local(value):
  267. if not is_in_scope(value):
  268. return "undefined"
  269. custom_summary = get_custom_summary(value)
  270. if custom_summary is not None:
  271. return custom_summary
  272. vals = []
  273. max_vals = 7
  274. for child in value.children:
  275. vals.append(child.value)
  276. if len(vals) > max_vals:
  277. vals.append("...")
  278. break
  279. return "{" + ", ".join(vals) + "}"
  280. def Table(value: lldb.SBValue, internal_dict):
  281. if is_local(value):
  282. if not is_in_scope(value):
  283. return "undefined"
  284. custom_summary = get_custom_summary(value)
  285. if custom_summary is not None:
  286. return custom_summary
  287. fields = []
  288. for i in range(value.num_children):
  289. key = value[i].name
  290. val = value[i].summary
  291. fields.append(f"{key}: {val}")
  292. return "Table({" + ", ".join(fields) + "})"
  293. def HashSet(value: lldb.SBValue, internal_dict):
  294. if is_local(value):
  295. if not is_in_scope(value):
  296. return "undefined"
  297. custom_summary = get_custom_summary(value)
  298. if custom_summary is not None:
  299. return custom_summary
  300. fields = []
  301. for i in range(value.num_children):
  302. fields.append(f"{value[i].summary}")
  303. return "HashSet({" + ", ".join(fields) + "})"
  304. def StringTable(value: lldb.SBValue, internal_dict):
  305. if is_local(value):
  306. if not is_in_scope(value):
  307. return "undefined"
  308. custom_summary = get_custom_summary(value)
  309. if not custom_summary is None:
  310. return custom_summary
  311. fields = []
  312. for i in range(value.num_children - 1):
  313. key = value[i].name
  314. val = value[i].summary
  315. fields.append(f"{key}: {val}")
  316. mode = value[value.num_children - 1].summary
  317. return "StringTable({" + ", ".join(fields) + f"}}, mode={mode})"
  318. def Sequence(value: lldb.SBValue, internal_dict):
  319. if is_local(value):
  320. if not is_in_scope(value):
  321. return "undefined"
  322. custom_summary = get_custom_summary(value)
  323. if not custom_summary is None:
  324. return custom_summary
  325. return "@[" + ", ".join([value[i].summary for i in range(value.num_children)]) + "]"
  326. class StringChildrenProvider:
  327. def __init__(self, value: lldb.SBValue, internalDict):
  328. self.value = value
  329. self.data_type: lldb.SBType
  330. if not NIM_IS_V2:
  331. self.data_type = self.value.target.FindFirstType("char")
  332. self.first_element: lldb.SBValue
  333. self.update()
  334. self.count = 0
  335. def num_children(self):
  336. return self.count
  337. def get_child_index(self, name):
  338. return int(name.lstrip("[").rstrip("]"))
  339. def get_child_at_index(self, index):
  340. offset = index * self.data_size
  341. return self.first_element.CreateChildAtOffset("[" + str(index) + "]", offset, self.data_type)
  342. def get_data(self) -> lldb.SBValue:
  343. return self.value["p"]["data"] if NIM_IS_V2 else self.value["data"]
  344. def get_len(self) -> int:
  345. if NIM_IS_V2:
  346. if self.value["p"].unsigned == 0:
  347. return 0
  348. size = int(self.value["len"].signed)
  349. if size == 0:
  350. return 0
  351. data = self.value["p"]["data"]
  352. # Check if first element is NULL
  353. base_data_type = data.type.GetArrayElementType().GetTypedefedType()
  354. cast = data.Cast(base_data_type)
  355. if cast.unsigned == 0:
  356. return 0
  357. else:
  358. if self.value.type.is_pointer and self.value.unsigned == 0:
  359. return 0
  360. size = int(self.value["Sup"]["len"].unsigned)
  361. if size == 0:
  362. return 0
  363. data = self.value["data"]
  364. # Check if first element is NULL
  365. base_data_type = self.value.target.FindFirstType("char")
  366. cast = data.Cast(base_data_type)
  367. if cast.unsigned == 0:
  368. return 0
  369. return size
  370. def update(self):
  371. if is_local(self.value):
  372. if not is_in_scope(self.value):
  373. return
  374. data = self.get_data()
  375. size = self.get_len()
  376. self.count = size
  377. self.first_element = data
  378. if NIM_IS_V2:
  379. self.data_type = data.type.GetArrayElementType().GetTypedefedType()
  380. self.data_size = self.data_type.GetByteSize()
  381. def has_children(self):
  382. return bool(self.num_children())
  383. class ArrayChildrenProvider:
  384. def __init__(self, value: lldb.SBValue, internalDict):
  385. self.value = value
  386. self.data_type: lldb.SBType
  387. self.first_element: lldb.SBValue
  388. self.update()
  389. def num_children(self):
  390. return self.has_children() and self.value.num_children
  391. def get_child_index(self, name: str):
  392. return int(name.lstrip("[").rstrip("]"))
  393. def get_child_at_index(self, index):
  394. offset = index * self.value[index].GetByteSize()
  395. return self.first_element.CreateChildAtOffset("[" + str(index) + "]", offset, self.data_type)
  396. def update(self):
  397. if not self.has_children():
  398. return
  399. self.first_element = self.value[0]
  400. self.data_type = self.value.type.GetArrayElementType()
  401. def has_children(self):
  402. if is_local(self.value):
  403. if not is_in_scope(self.value):
  404. return False
  405. return bool(self.value.num_children)
  406. class SeqChildrenProvider:
  407. def __init__(self, value: lldb.SBValue, internalDict):
  408. self.value = value
  409. self.data_type: lldb.SBType
  410. self.first_element: lldb.SBValue
  411. self.data: lldb.SBValue
  412. self.count = 0
  413. self.update()
  414. def num_children(self):
  415. return self.count
  416. def get_child_index(self, name: str):
  417. return int(name.lstrip("[").rstrip("]"))
  418. def get_child_at_index(self, index):
  419. offset = index * self.data[index].GetByteSize()
  420. return self.first_element.CreateChildAtOffset("[" + str(index) + "]", offset, self.data_type)
  421. def get_data(self) -> lldb.SBValue:
  422. return self.value["p"]["data"] if NIM_IS_V2 else self.value["data"]
  423. def get_len(self) -> lldb.SBValue:
  424. return self.value["len"] if NIM_IS_V2 else self.value["Sup"]["len"]
  425. def update(self):
  426. self.count = 0
  427. if is_local(self.value):
  428. if not is_in_scope(self.value):
  429. return
  430. self.count = self.get_len().unsigned
  431. if not self.has_children():
  432. return
  433. data = self.get_data()
  434. self.data_type = data.type.GetArrayElementType()
  435. self.data = data.Cast(self.data_type.GetArrayType(self.num_children()))
  436. self.first_element = self.data
  437. def has_children(self):
  438. return bool(self.num_children())
  439. class ObjectChildrenProvider:
  440. def __init__(self, value: lldb.SBValue, internalDict):
  441. self.value = value
  442. self.data_type: lldb.SBType
  443. self.first_element: lldb.SBValue
  444. self.data: lldb.SBValue
  445. self.children: OrderedDict[str, int] = OrderedDict()
  446. self.child_list: list[lldb.SBValue] = []
  447. self.update()
  448. def num_children(self):
  449. return len(self.children)
  450. def get_child_index(self, name: str):
  451. return self.children[name]
  452. def get_child_at_index(self, index):
  453. return self.child_list[index]
  454. def populate_children(self):
  455. self.children.clear()
  456. self.child_list = []
  457. if is_local(self.value):
  458. if not is_in_scope(self.value):
  459. return
  460. stack = [self.value.GetNonSyntheticValue()]
  461. index = 0
  462. while stack:
  463. cur_val = stack.pop()
  464. if cur_val.type.is_pointer and cur_val.unsigned == 0:
  465. continue
  466. while cur_val.type.is_pointer:
  467. cur_val = cur_val.Dereference()
  468. # Add super objects if they exist
  469. if cur_val.num_children > 0 and cur_val[0].name == "Sup" and cur_val[0].type.name.startswith("tyObject"):
  470. stack.append(cur_val[0])
  471. for child in cur_val.children:
  472. child = child.GetNonSyntheticValue()
  473. if child.name == "Sup":
  474. continue
  475. self.children[child.name] = index
  476. self.child_list.append(child)
  477. index += 1
  478. def update(self):
  479. self.populate_children()
  480. def has_children(self):
  481. return bool(self.num_children())
  482. class HashSetChildrenProvider:
  483. def __init__(self, value: lldb.SBValue, internalDict):
  484. self.value = value
  485. self.child_list: list[lldb.SBValue] = []
  486. self.update()
  487. def num_children(self):
  488. return len(self.child_list)
  489. def get_child_index(self, name: str):
  490. return int(name.lstrip("[").rstrip("]"))
  491. def get_child_at_index(self, index):
  492. return self.child_list[index]
  493. def get_data(self) -> lldb.SBValue:
  494. return self.value["data"]["p"]["data"] if NIM_IS_V2 else self.value["data"]["data"]
  495. def get_len(self) -> lldb.SBValue:
  496. return self.value["data"]["len"] if NIM_IS_V2 else self.value["data"]["Sup"]["len"]
  497. def update(self):
  498. self.child_list = []
  499. if is_local(self.value):
  500. if not is_in_scope(self.value):
  501. return
  502. tuple_len = int(self.get_len().unsigned)
  503. tuple = self.get_data()
  504. base_data_type = tuple.type.GetArrayElementType()
  505. cast = tuple.Cast(base_data_type.GetArrayType(tuple_len))
  506. index = 0
  507. for i in range(tuple_len):
  508. el = cast[i]
  509. field0 = int(el[0].unsigned)
  510. if field0 == 0:
  511. continue
  512. key = el[1]
  513. child = key.CreateValueFromAddress(f"[{str(index)}]", key.GetLoadAddress(), key.GetType())
  514. index += 1
  515. self.child_list.append(child)
  516. def has_children(self):
  517. return bool(self.num_children())
  518. class SetCharChildrenProvider:
  519. def __init__(self, value: lldb.SBValue, internalDict):
  520. self.value = value
  521. self.ty = self.value.target.FindFirstType("char")
  522. self.child_list: list[lldb.SBValue] = []
  523. self.update()
  524. def num_children(self):
  525. return len(self.child_list)
  526. def get_child_index(self, name: str):
  527. return int(name.lstrip("[").rstrip("]"))
  528. def get_child_at_index(self, index):
  529. return self.child_list[index]
  530. def update(self):
  531. self.child_list = []
  532. if is_local(self.value):
  533. if not is_in_scope(self.value):
  534. return
  535. cur_pos = 0
  536. for child in self.value.children:
  537. child_val = child.signed
  538. if child_val != 0:
  539. temp = child_val
  540. num_bits = 8
  541. while temp != 0:
  542. is_set = temp & 1
  543. if is_set == 1:
  544. data = lldb.SBData.CreateDataFromInt(cur_pos)
  545. child = self.value.synthetic_child_from_data(f"[{len(self.child_list)}]", data, self.ty)
  546. self.child_list.append(child)
  547. temp = temp >> 1
  548. cur_pos += 1
  549. num_bits -= 1
  550. cur_pos += num_bits
  551. else:
  552. cur_pos += 8
  553. def has_children(self):
  554. return bool(self.num_children())
  555. def create_set_children(value: lldb.SBValue, child_type: lldb.SBType, starting_pos: int) -> list[lldb.SBValue]:
  556. child_list: list[lldb.SBValue] = []
  557. cur_pos = starting_pos
  558. if value.num_children > 0:
  559. children = value.children
  560. else:
  561. children = [value]
  562. for child in children:
  563. child_val = child.signed
  564. if child_val != 0:
  565. temp = child_val
  566. num_bits = 8
  567. while temp != 0:
  568. is_set = temp & 1
  569. if is_set == 1:
  570. data = lldb.SBData.CreateDataFromInt(cur_pos)
  571. child = value.synthetic_child_from_data(f"[{len(child_list)}]", data, child_type)
  572. child_list.append(child)
  573. temp = temp >> 1
  574. cur_pos += 1
  575. num_bits -= 1
  576. cur_pos += num_bits
  577. else:
  578. cur_pos += 8
  579. return child_list
  580. class SetIntChildrenProvider:
  581. def __init__(self, value: lldb.SBValue, internalDict):
  582. self.value = value
  583. self.ty = self.value.target.FindFirstType(f"NI64")
  584. self.child_list: list[lldb.SBValue] = []
  585. self.update()
  586. def num_children(self):
  587. return len(self.child_list)
  588. def get_child_index(self, name: str):
  589. return int(name.lstrip("[").rstrip("]"))
  590. def get_child_at_index(self, index):
  591. return self.child_list[index]
  592. def update(self):
  593. self.child_list = []
  594. if is_local(self.value):
  595. if not is_in_scope(self.value):
  596. return
  597. bits = self.value.GetByteSize() * 8
  598. starting_pos = -(bits // 2)
  599. self.child_list = create_set_children(self.value, self.ty, starting_pos)
  600. def has_children(self):
  601. return bool(self.num_children())
  602. class SetUIntChildrenProvider:
  603. def __init__(self, value: lldb.SBValue, internalDict):
  604. self.value = value
  605. self.ty = self.value.target.FindFirstType(f"NU64")
  606. self.child_list: list[lldb.SBValue] = []
  607. self.update()
  608. def num_children(self):
  609. return len(self.child_list)
  610. def get_child_index(self, name: str):
  611. return int(name.lstrip("[").rstrip("]"))
  612. def get_child_at_index(self, index):
  613. return self.child_list[index]
  614. def update(self):
  615. self.child_list = []
  616. if is_local(self.value):
  617. if not is_in_scope(self.value):
  618. return
  619. self.child_list = create_set_children(self.value, self.ty, starting_pos=0)
  620. def has_children(self):
  621. return bool(self.num_children())
  622. class SetEnumChildrenProvider:
  623. def __init__(self, value: lldb.SBValue, internalDict):
  624. self.value = value
  625. self.ty = self.value.target.FindFirstType(self.value.type.name.replace("tySet_", ""))
  626. self.child_list: list[lldb.SBValue] = []
  627. self.update()
  628. def num_children(self):
  629. return len(self.child_list)
  630. def get_child_index(self, name: str):
  631. return int(name.lstrip("[").rstrip("]"))
  632. def get_child_at_index(self, index):
  633. return self.child_list[index]
  634. def update(self):
  635. if is_local(self.value):
  636. if not is_in_scope(self.value):
  637. return
  638. self.child_list = create_set_children(self.value, self.ty, starting_pos=0)
  639. def has_children(self):
  640. return bool(self.num_children())
  641. class TableChildrenProvider:
  642. def __init__(self, value: lldb.SBValue, internalDict):
  643. self.value = value
  644. self.children: OrderedDict[str, int] = OrderedDict()
  645. self.child_list: list[lldb.SBValue] = []
  646. self.update()
  647. def num_children(self):
  648. return len(self.child_list)
  649. def get_child_index(self, name: str):
  650. return self.children[name]
  651. def get_child_at_index(self, index):
  652. return self.child_list[index]
  653. def get_data(self) -> lldb.SBValue:
  654. return self.value["data"]["p"]["data"] if NIM_IS_V2 else self.value["data"]["data"]
  655. def get_len(self) -> lldb.SBValue:
  656. return self.value["data"]["len"] if NIM_IS_V2 else self.value["data"]["Sup"]["len"]
  657. def update(self):
  658. self.child_list = []
  659. if is_local(self.value):
  660. if not is_in_scope(self.value):
  661. return
  662. tuple_len = int(self.get_len().unsigned)
  663. tuple = self.get_data()
  664. base_data_type = tuple.type.GetArrayElementType()
  665. cast = tuple.Cast(base_data_type.GetArrayType(tuple_len))
  666. index = 0
  667. for i in range(tuple_len):
  668. el = cast[i]
  669. field0 = int(el[0].unsigned)
  670. if field0 == 0:
  671. continue
  672. key = el[1]
  673. val = el[2]
  674. key_summary = key.summary
  675. child = self.value.CreateValueFromAddress(key_summary, val.GetLoadAddress(), val.GetType())
  676. self.child_list.append(child)
  677. self.children[key_summary] = index
  678. index += 1
  679. def has_children(self):
  680. return bool(self.num_children())
  681. class StringTableChildrenProvider:
  682. def __init__(self, value: lldb.SBValue, internalDict):
  683. self.value = value
  684. self.children: OrderedDict[str, int] = OrderedDict()
  685. self.child_list: list[lldb.SBValue] = []
  686. self.update()
  687. def num_children(self):
  688. return len(self.child_list)
  689. def get_child_index(self, name: str):
  690. return self.children[name]
  691. def get_child_at_index(self, index):
  692. return self.child_list[index]
  693. def get_data(self) -> lldb.SBValue:
  694. return self.value["data"]["p"]["data"] if NIM_IS_V2 else self.value["data"]["data"]
  695. def get_len(self) -> lldb.SBValue:
  696. return self.value["data"]["len"] if NIM_IS_V2 else self.value["data"]["Sup"]["len"]
  697. def update(self):
  698. self.children.clear()
  699. self.child_list = []
  700. if is_local(self.value):
  701. if not is_in_scope(self.value):
  702. return
  703. tuple_len = int(self.get_len().unsigned)
  704. tuple = self.get_data()
  705. base_data_type = tuple.type.GetArrayElementType()
  706. cast = tuple.Cast(base_data_type.GetArrayType(tuple_len))
  707. index = 0
  708. for i in range(tuple_len):
  709. el = cast[i]
  710. field0 = int(el[2].unsigned)
  711. if field0 == 0:
  712. continue
  713. key = el[0]
  714. val = el[1]
  715. child = val.CreateValueFromAddress(key.summary, val.GetLoadAddress(), val.GetType())
  716. self.child_list.append(child)
  717. self.children[key.summary] = index
  718. index += 1
  719. self.child_list.append(self.value["mode"])
  720. self.children["mode"] = index
  721. def has_children(self):
  722. return bool(self.num_children())
  723. class LLDBDynamicObjectProvider:
  724. def __init__(self, value: lldb.SBValue, internalDict):
  725. value = value.GetNonSyntheticValue()
  726. self.value: lldb.SBValue = value[0]
  727. self.children: OrderedDict[str, int] = OrderedDict()
  728. self.child_list: list[lldb.SBValue] = []
  729. while self.value.type.is_pointer:
  730. self.value = self.value.Dereference()
  731. self.update()
  732. def num_children(self):
  733. return len(self.child_list)
  734. def get_child_index(self, name: str):
  735. return self.children[name]
  736. def get_child_at_index(self, index):
  737. return self.child_list[index]
  738. def update(self):
  739. self.children.clear()
  740. self.child_list = []
  741. for i, child in enumerate(self.value.children):
  742. name = child.name.strip('"')
  743. new_child = child.CreateValueFromAddress(name, child.GetLoadAddress(), child.GetType())
  744. self.children[name] = i
  745. self.child_list.append(new_child)
  746. def has_children(self):
  747. return bool(self.num_children())
  748. class LLDBBasicObjectProvider:
  749. def __init__(self, value: lldb.SBValue, internalDict):
  750. self.value: lldb.SBValue = value
  751. def num_children(self):
  752. if self.value is not None:
  753. return self.value.num_children
  754. return 0
  755. def get_child_index(self, name: str):
  756. return self.value.GetIndexOfChildWithName(name)
  757. def get_child_at_index(self, index):
  758. return self.value.GetChildAtIndex(index)
  759. def update(self):
  760. pass
  761. def has_children(self):
  762. return self.num_children() > 0
  763. class CustomObjectChildrenProvider:
  764. """
  765. This children provider handles values returned from lldbDebugSynthetic*
  766. Nim procedures
  767. """
  768. def __init__(self, value: lldb.SBValue, internalDict):
  769. self.value: lldb.SBValue = get_custom_synthetic(value) or value
  770. if "lldbdynamicobject" in self.value.type.name.lower():
  771. self.provider = LLDBDynamicObjectProvider(self.value, internalDict)
  772. else:
  773. self.provider = LLDBBasicObjectProvider(self.value, internalDict)
  774. def num_children(self):
  775. return self.provider.num_children()
  776. def get_child_index(self, name: str):
  777. return self.provider.get_child_index(name)
  778. def get_child_at_index(self, index):
  779. return self.provider.get_child_at_index(index)
  780. def update(self):
  781. self.provider.update()
  782. def has_children(self):
  783. return self.provider.has_children()
  784. def echo(debugger: lldb.SBDebugger, command: str, result, internal_dict):
  785. debugger.HandleCommand("po " + command)
  786. SUMMARY_FUNCTIONS: dict[str, lldb.SBFunction] = {}
  787. SYNTHETIC_FUNCTIONS: dict[str, lldb.SBFunction] = {}
  788. def get_custom_summary(value: lldb.SBValue) -> Union[str, None]:
  789. """Get a custom summary if a function exists for it"""
  790. value = value.GetNonSyntheticValue()
  791. if value.GetAddress().GetOffset() == 0:
  792. return None
  793. base_type = get_base_type(value.type)
  794. fn = SUMMARY_FUNCTIONS.get(base_type.name)
  795. if fn is None:
  796. return None
  797. fn_type: lldb.SBType = fn.type
  798. arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
  799. first_type = arg_types.GetTypeAtIndex(0)
  800. while value.type.is_pointer:
  801. value = value.Dereference()
  802. if first_type.is_pointer:
  803. command = f"{fn.name}(({first_type.name})" + str(value.GetLoadAddress()) + ");"
  804. else:
  805. command = f"{fn.name}(*({first_type.GetPointerType().name})" + str(value.GetLoadAddress()) + ");"
  806. res = executeCommand(command)
  807. if res.error.fail:
  808. return None
  809. return res.summary.strip('"')
  810. def get_custom_value_summary(value: lldb.SBValue) -> Union[str, None]:
  811. """Get a custom summary if a function exists for it"""
  812. fn: lldb.SBFunction = SUMMARY_FUNCTIONS.get(value.type.name)
  813. if fn is None:
  814. return None
  815. command = f"{fn.name}(({value.type.name})" + str(value.signed) + ");"
  816. res = executeCommand(command)
  817. if res.error.fail:
  818. return None
  819. return res.summary.strip('"')
  820. def get_custom_synthetic(value: lldb.SBValue) -> Union[lldb.SBValue, None]:
  821. """Get a custom synthetic object if a function exists for it"""
  822. value = value.GetNonSyntheticValue()
  823. if value.GetAddress().GetOffset() == 0:
  824. return None
  825. base_type = get_base_type(value.type)
  826. fn = SYNTHETIC_FUNCTIONS.get(base_type.name)
  827. if fn is None:
  828. return None
  829. fn_type: lldb.SBType = fn.type
  830. arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
  831. first_type = arg_types.GetTypeAtIndex(0)
  832. while value.type.is_pointer:
  833. value = value.Dereference()
  834. if first_type.is_pointer:
  835. first_arg = f"({first_type.name}){value.GetLoadAddress()}"
  836. else:
  837. first_arg = f"*({first_type.GetPointerType().name}){value.GetLoadAddress()}"
  838. if arg_types.GetSize() > 1 and fn.GetArgumentName(1) == "Result":
  839. ret_type = arg_types.GetTypeAtIndex(1)
  840. ret_type = get_base_type(ret_type)
  841. command = f"""
  842. {ret_type.name} lldbT;
  843. nimZeroMem((void*)(&lldbT), sizeof({ret_type.name}));
  844. {fn.name}(({first_arg}), (&lldbT));
  845. lldbT;
  846. """
  847. else:
  848. command = f"{fn.name}({first_arg});"
  849. res = executeCommand(command)
  850. if res.error.fail:
  851. print(res.error)
  852. return None
  853. return res
  854. def get_base_type(ty: lldb.SBType) -> lldb.SBType:
  855. """Get the base type of the type"""
  856. temp = ty
  857. while temp.IsPointerType():
  858. temp = temp.GetPointeeType()
  859. return temp
  860. def use_base_type(ty: lldb.SBType) -> bool:
  861. types_to_check = [
  862. "NF",
  863. "NF32",
  864. "NF64",
  865. "NI",
  866. "NI8",
  867. "NI16",
  868. "NI32",
  869. "NI64",
  870. "bool",
  871. "NIM_BOOL",
  872. "NU",
  873. "NU8",
  874. "NU16",
  875. "NU32",
  876. "NU64",
  877. ]
  878. for type_to_check in types_to_check:
  879. if ty.name.startswith(type_to_check):
  880. return False
  881. return True
  882. def breakpoint_function_wrapper(frame: lldb.SBFrame, bp_loc, internal_dict):
  883. """This allows function calls to Nim for custom object summaries and synthetic children"""
  884. debugger = lldb.debugger
  885. global SUMMARY_FUNCTIONS
  886. global SYNTHETIC_FUNCTIONS
  887. global NIM_IS_V2
  888. for tname, fn in SYNTHETIC_FUNCTIONS.items():
  889. debugger.HandleCommand(f"type synthetic delete -w nim {tname}")
  890. SUMMARY_FUNCTIONS = {}
  891. SYNTHETIC_FUNCTIONS = {}
  892. target: lldb.SBTarget = debugger.GetSelectedTarget()
  893. NIM_IS_V2 = target.FindFirstType("TNimTypeV2").IsValid()
  894. module = frame.GetSymbolContext(lldb.eSymbolContextModule).module
  895. for sym in module:
  896. if (
  897. not sym.name.startswith("lldbDebugSummary")
  898. and not sym.name.startswith("lldbDebugSynthetic")
  899. and not sym.name.startswith("dollar___")
  900. ):
  901. continue
  902. fn_syms: lldb.SBSymbolContextList = target.FindFunctions(sym.name)
  903. if not fn_syms.GetSize() > 0:
  904. continue
  905. fn_sym: lldb.SBSymbolContext = fn_syms.GetContextAtIndex(0)
  906. fn: lldb.SBFunction = fn_sym.function
  907. fn_type: lldb.SBType = fn.type
  908. arg_types: lldb.SBTypeList = fn_type.GetFunctionArgumentTypes()
  909. if arg_types.GetSize() > 1 and fn.GetArgumentName(1) == "Result":
  910. pass # don't continue
  911. elif arg_types.GetSize() != 1:
  912. continue
  913. arg_type: lldb.SBType = arg_types.GetTypeAtIndex(0)
  914. if use_base_type(arg_type):
  915. arg_type = get_base_type(arg_type)
  916. if sym.name.startswith("lldbDebugSummary") or sym.name.startswith("dollar___"):
  917. SUMMARY_FUNCTIONS[arg_type.name] = fn
  918. elif sym.name.startswith("lldbDebugSynthetic"):
  919. SYNTHETIC_FUNCTIONS[arg_type.name] = fn
  920. debugger.HandleCommand(
  921. f"type synthetic add -w nim -l {__name__}.CustomObjectChildrenProvider {arg_type.name}"
  922. )
  923. def executeCommand(command, *args):
  924. debugger = lldb.debugger
  925. process = debugger.GetSelectedTarget().GetProcess()
  926. frame: lldb.SBFrame = process.GetSelectedThread().GetSelectedFrame()
  927. expr_options = lldb.SBExpressionOptions()
  928. expr_options.SetIgnoreBreakpoints(False)
  929. expr_options.SetFetchDynamicValue(lldb.eDynamicCanRunTarget)
  930. expr_options.SetTimeoutInMicroSeconds(30 * 1000 * 1000) # 30 second timeout
  931. expr_options.SetTryAllThreads(True)
  932. expr_options.SetUnwindOnError(False)
  933. expr_options.SetGenerateDebugInfo(True)
  934. expr_options.SetLanguage(lldb.eLanguageTypeC)
  935. expr_options.SetCoerceResultToId(True)
  936. res = frame.EvaluateExpression(command, expr_options)
  937. return res
  938. def __lldb_init_module(debugger, internal_dict):
  939. # fmt: off
  940. debugger.HandleCommand(f"breakpoint command add -F {__name__}.breakpoint_function_wrapper --script-type python 1")
  941. debugger.HandleCommand(f"type summary add -w nim -n sequence -F {__name__}.Sequence -x tySequence_+[[:alnum:]]+$")
  942. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SeqChildrenProvider -x tySequence_+[[:alnum:]]+$")
  943. debugger.HandleCommand(f"type summary add -w nim -n chararray -F {__name__}.CharArray -x char\s+[\d+]")
  944. debugger.HandleCommand(f"type summary add -w nim -n array -F {__name__}.Array -x tyArray_+[[:alnum:]]+")
  945. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.ArrayChildrenProvider -x tyArray_+[[:alnum:]]+")
  946. debugger.HandleCommand(f"type summary add -w nim -n string -F {__name__}.NimString NimStringDesc")
  947. debugger.HandleCommand(f"type summary add -w nim -n stringv2 -F {__name__}.NimString -x NimStringV2$")
  948. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringChildrenProvider -x NimStringV2$")
  949. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringChildrenProvider -x NimStringDesc$")
  950. debugger.HandleCommand(f"type summary add -w nim -n cstring -F {__name__}.NCSTRING NCSTRING")
  951. debugger.HandleCommand(f"type summary add -w nim -n object -F {__name__}.ObjectV2 -x tyObject_+[[:alnum:]]+_+[[:alnum:]]+")
  952. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.ObjectChildrenProvider -x tyObject_+[[:alnum:]]+_+[[:alnum:]]+$")
  953. debugger.HandleCommand(f"type summary add -w nim -n tframe -F {__name__}.ObjectV2 -x TFrame$")
  954. debugger.HandleCommand(f"type summary add -w nim -n rootobj -F {__name__}.ObjectV2 -x RootObj$")
  955. debugger.HandleCommand(f"type summary add -w nim -n enum -F {__name__}.Enum -x tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
  956. debugger.HandleCommand(f"type summary add -w nim -n hashset -F {__name__}.HashSet -x tyObject_+HashSet_+[[:alnum:]]+")
  957. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.HashSetChildrenProvider -x tyObject_+HashSet_+[[:alnum:]]+")
  958. debugger.HandleCommand(f"type summary add -w nim -n rope -F {__name__}.Rope -x tyObject_+Rope[[:alnum:]]+_+[[:alnum:]]+")
  959. debugger.HandleCommand(f"type summary add -w nim -n setuint -F {__name__}.Set -x tySet_+tyInt_+[[:alnum:]]+")
  960. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetIntChildrenProvider -x tySet_+tyInt[0-9]+_+[[:alnum:]]+")
  961. debugger.HandleCommand(f"type summary add -w nim -n setint -F {__name__}.Set -x tySet_+tyInt[0-9]+_+[[:alnum:]]+")
  962. debugger.HandleCommand(f"type summary add -w nim -n setuint2 -F {__name__}.Set -x tySet_+tyUInt[0-9]+_+[[:alnum:]]+")
  963. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetUIntChildrenProvider -x tySet_+tyUInt[0-9]+_+[[:alnum:]]+")
  964. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetUIntChildrenProvider -x tySet_+tyInt_+[[:alnum:]]+")
  965. debugger.HandleCommand(f"type summary add -w nim -n setenum -F {__name__}.EnumSet -x tySet_+tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
  966. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetEnumChildrenProvider -x tySet_+tyEnum_+[[:alnum:]]+_+[[:alnum:]]+")
  967. debugger.HandleCommand(f"type summary add -w nim -n setchar -F {__name__}.Set -x tySet_+tyChar_+[[:alnum:]]+")
  968. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.SetCharChildrenProvider -x tySet_+tyChar_+[[:alnum:]]+")
  969. debugger.HandleCommand(f"type summary add -w nim -n table -F {__name__}.Table -x tyObject_+Table_+[[:alnum:]]+")
  970. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.TableChildrenProvider -x tyObject_+Table_+[[:alnum:]]+")
  971. debugger.HandleCommand(f"type summary add -w nim -n stringtable -F {__name__}.StringTable -x tyObject_+StringTableObj_+[[:alnum:]]+")
  972. debugger.HandleCommand(f"type synthetic add -w nim -l {__name__}.StringTableChildrenProvider -x tyObject_+StringTableObj_+[[:alnum:]]+")
  973. debugger.HandleCommand(f"type summary add -w nim -n tuple2 -F {__name__}.Tuple -x tyObject_+Tuple_+[[:alnum:]]+")
  974. debugger.HandleCommand(f"type summary add -w nim -n tuple -F {__name__}.Tuple -x tyTuple_+[[:alnum:]]+")
  975. debugger.HandleCommand(f"type summary add -w nim -n float -F {__name__}.Float NF")
  976. debugger.HandleCommand(f"type summary add -w nim -n float32 -F {__name__}.Float NF32")
  977. debugger.HandleCommand(f"type summary add -w nim -n float64 -F {__name__}.Float NF64")
  978. debugger.HandleCommand(f"type summary add -w nim -n integer -F {__name__}.Number -x NI")
  979. debugger.HandleCommand(f"type summary add -w nim -n integer8 -F {__name__}.Number -x NI8")
  980. debugger.HandleCommand(f"type summary add -w nim -n integer16 -F {__name__}.Number -x NI16")
  981. debugger.HandleCommand(f"type summary add -w nim -n integer32 -F {__name__}.Number -x NI32")
  982. debugger.HandleCommand(f"type summary add -w nim -n integer64 -F {__name__}.Number -x NI64")
  983. debugger.HandleCommand(f"type summary add -w nim -n bool -F {__name__}.Bool -x bool")
  984. debugger.HandleCommand(f"type summary add -w nim -n bool2 -F {__name__}.Bool -x NIM_BOOL")
  985. debugger.HandleCommand(f"type summary add -w nim -n uinteger -F {__name__}.UnsignedNumber -x NU")
  986. debugger.HandleCommand(f"type summary add -w nim -n uinteger8 -F {__name__}.UnsignedNumber -x NU8")
  987. debugger.HandleCommand(f"type summary add -w nim -n uinteger16 -F {__name__}.UnsignedNumber -x NU16")
  988. debugger.HandleCommand(f"type summary add -w nim -n uinteger32 -F {__name__}.UnsignedNumber -x NU32")
  989. debugger.HandleCommand(f"type summary add -w nim -n uinteger64 -F {__name__}.UnsignedNumber -x NU64")
  990. debugger.HandleCommand("type category enable nim")
  991. debugger.HandleCommand(f"command script add -f {__name__}.echo echo")
  992. # fmt: on