heapdumprepl.nim 4.2 KB

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