heapdumprepl.nim 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. include std/prelude
  2. import intsets
  3. type
  4. NodeKind = enum
  5. internal, local, localInvalid, global, globalInvalid
  6. Color = enum
  7. white, grey, black
  8. Node = ref object
  9. id, rc: int
  10. kids: seq[int]
  11. k: NodeKind
  12. col: Color
  13. Graph = object
  14. nodes: Table[int, Node]
  15. roots: Table[int, NodeKind]
  16. proc add(father: Node; son: int) =
  17. father.kids.add(son)
  18. proc renderNode(g: Graph; id: int) =
  19. let n = g.nodes[id]
  20. echo n[]
  21. proc toNodeId(aliases: var Table[string,int]; s: string): int =
  22. result = aliases.getOrDefault(s)
  23. if result == 0:
  24. if s.startsWith("x"):
  25. discard s.parseHex(result, 1)
  26. else:
  27. result = s.parseInt
  28. proc parseHex(s: string): int =
  29. discard parseutils.parseHex(s, result, 0)
  30. proc reachable(g: Graph; stack: var seq[int]; goal: int): bool =
  31. var t = initIntSet()
  32. while stack.len > 0:
  33. let it = stack.pop
  34. if not t.containsOrIncl(it):
  35. if it == goal: return true
  36. if it in g.nodes:
  37. for kid in g.nodes[it].kids:
  38. stack.add(kid)
  39. const Help = """
  40. quit -- quits this REPL
  41. locals, l -- output the list of local stack roots
  42. globals, g -- output the list of global roots
  43. alias name addr -- give addr a name. start 'addr' with 'x' for hexadecimal
  44. notation
  45. print name|addr -- print a node by name or address
  46. reachable,r l|g|node dest -- outputs TRUE or FALSE depending on whether
  47. dest is reachable by (l)ocals, (g)lobals or by the
  48. other given node. Nodes can be node names or node
  49. addresses.
  50. """
  51. proc repl(g: Graph) =
  52. var aliases = initTable[string,int]()
  53. while true:
  54. let line = stdin.readLine()
  55. let data = line.split()
  56. if data.len == 0: continue
  57. case data[0]
  58. of "quit":
  59. break
  60. of "help":
  61. echo Help
  62. of "locals", "l":
  63. for k,v in g.roots:
  64. if v == local: renderNode(g, k)
  65. of "globals", "g":
  66. for k,v in g.roots:
  67. if v == global: renderNode(g, k)
  68. of "alias", "a":
  69. # generate alias
  70. if data.len == 3:
  71. aliases[data[1]] = toNodeId(aliases, data[2])
  72. of "print", "p":
  73. if data.len == 2:
  74. renderNode(g, toNodeId(aliases, data[1]))
  75. of "reachable", "r":
  76. if data.len == 3:
  77. var stack: seq[int] = @[]
  78. case data[1]
  79. of "locals", "l":
  80. for k,v in g.roots:
  81. if v == local: stack.add k
  82. of "globals", "g":
  83. for k,v in g.roots:
  84. if v == global: stack.add k
  85. else:
  86. stack.add(toNodeId(aliases, data[1]))
  87. let goal = toNodeId(aliases, data[2])
  88. echo reachable(g, stack, goal)
  89. else: discard
  90. proc importData(input: string): Graph =
  91. #c_fprintf(file, "%s %p %d rc=%ld color=%c\n",
  92. # msg, c, kind, c.refcount shr rcShift, col)
  93. # cell 0x10a908190 22 rc=2 color=w
  94. var i: File
  95. var
  96. nodes = initTable[int, Node]()
  97. roots = initTable[int, NodeKind]()
  98. if open(i, input):
  99. var currNode: Node
  100. for line in lines(i):
  101. let data = line.split()
  102. if data.len == 0: continue
  103. case data[0]
  104. of "end":
  105. currNode = nil
  106. of "cell":
  107. let rc = parseInt(data[3].substr("rc=".len))
  108. let col = case data[4].substr("color=".len)
  109. of "b": black
  110. of "w": white
  111. of "g": grey
  112. else: (assert(false); grey)
  113. let id = parseHex(data[1])
  114. currNode = Node(id: id,
  115. k: roots.getOrDefault(id),
  116. rc: rc, col: col)
  117. nodes[currNode.id] = currNode
  118. of "child":
  119. assert currNode != nil
  120. currNode.add parseHex(data[1])
  121. of "global_root":
  122. roots[data[1].parseHex] = global
  123. of "global_root_invalid":
  124. roots[data[1].parseHex] = globalInvalid
  125. of "onstack":
  126. roots[data[1].parseHex] = local
  127. of "onstack_invalid":
  128. roots[data[1].parseHex] = localInvalid
  129. else: discard
  130. close(i)
  131. else:
  132. quit "error: cannot open " & input
  133. result.nodes = move nodes
  134. result.roots = move roots
  135. if paramCount() == 1:
  136. repl(importData(paramStr(1)))
  137. else:
  138. quit "usage: heapdumprepl inputfile"